Get data from a "log" table to a mySQL query - mysql

I need to check the data in a log table to see if the user has previously read a post. My log table is named foretag_kontaktervisadbrf2017 and it contains information about who has read a post. How can I edit my query so that i get information telling me if i have read a post or not?
This is my query so far:
SELECT
brfbolagsverket.BrfNamn
, brfextra.BrfId
, brfextra.Organisationsnr
, brfextra.Gatuadress
, brfextra.Ort
, brfextra.Lagenheter
, brfextra.ByggAr
, BrfHarFastighet.Fangdatum
FROM
(((((brfextra LEFT JOIN BrfHarFastighet ON brfextra.Organisationsnr = BrfHarFastighet.Organisationsnr)
LEFT JOIN brfkonkurs ON brfextra.Organisationsnr = brfkonkurs.Organisationsnr)
LEFT JOIN brfavford ON brfextra.Organisationsnr = brfavford.Organisationsnr)
LEFT JOIN brffusion ON brfextra.Organisationsnr = brffusion.Organisationsnr)
LEFT JOIN brflikvidation ON brfextra.Organisationsnr = brflikvidation.Organisationsnr)
LEFT JOIN brfbolagsverket ON brfextra.Organisationsnr = brfbolagsverket.Organisationsnr
WHERE
(((brfkonkurs.BolagetsStatusKod) IS NULL)
AND ((brfavford.BolagetsStatusKod) IS NULL)
AND ((brffusion.BolagetsStatusKod) IS NULL)
AND ((brflikvidation.BolagetsStatusKod) IS NULL OR (brflikvidation.BolagetsStatusKod) = 34))
In the result I need the following additional columns from the log table:
BrfId, BrfNamn, Organisationsnr, LogEntry
1, Billy, Organisationsnr, You have shown this post before
2, Carl, Organisationsnr, NULL
3, Kent, Organisationsnr, NULL
4, Sara, Organisationsnr, You have shown this post before
Please help with code I need to add to my query. I lack coding experience.

I would do this by adding a subselect like the example below. Hope it helps point you in the right direction.
SELECT
brfbolagsverket.BrfNamn
, CASE WHEN (SELECT COUNT(*) FROM foretag_kontaktervisadbrf2017 AS L WHERE L.Organisationsnr = B.Organisationsnr AND L.Foretag_kontaktID = 1247) > 0 THEN 'Lest' ELSE 'Inte lest' END AS NotificationRead
, brfextra.BrfId
, brfextra.Organisationsnr
, brfextra.Gatuadress
, brfextra.Ort
, brfextra.Lagenheter
, brfextra.ByggAr
, BrfHarFastighet.Fangdatum
FROM (((((
brfextra AS B
LEFT JOIN BrfHarFastighet ON brfextra.Organisationsnr = BrfHarFastighet.Organisationsnr)
LEFT JOIN brfkonkurs ON brfextra.Organisationsnr = brfkonkurs.Organisationsnr)
LEFT JOIN brfavford ON brfextra.Organisationsnr = brfavford.Organisationsnr)
LEFT JOIN brffusion ON brfextra.Organisationsnr = brffusion.Organisationsnr)
LEFT JOIN brflikvidation ON brfextra.Organisationsnr = brflikvidation.Organisationsnr)
LEFT JOIN brfbolagsverket ON brfextra.Organisationsnr = brfbolagsverket.Organisationsnr
WHERE (((brfkonkurs.BolagetsStatusKod) Is Null) AND ((brfavford.BolagetsStatusKod) Is Null) AND ((brffusion.BolagetsStatusKod) Is Null) AND ((brflikvidation.BolagetsStatusKod) Is Null Or (brflikvidation.BolagetsStatusKod)=34))

Im sorry if i post wrong - don't know how to reply properly to Werner Waage answer.
The query is slow when search gets more than 50-70 records - i tried to change to select like
(SELECT Foretag_kontaktervisadBrfID FROM foretag_kontaktervisadbrf2017 AS L WHERE L.Organisationsnr = B.Organisationsnr AND L.Foretag_kontaktID = '1247') AS NotificationRead
but its slow to.
My log table foretag_kontaktervisadbrf2017 have unique posts like this
Foretag_kontaktervisadBrfID, Foretag_kontaktID, Organisationsnr, Date001
1, Billy01, Acme_01, 2018-01-01
2, Carl01, Acme_02, 2018-01-02
3, Billy01, Acme_02, 2018-04-15
4, Carl01, Acme_03, 2018-14-14
Any way to get my previous speed back to the new query?
My original SQL-query worked fast even with results of 1000 records/post.

Here is another approach without using subselects, it assumes that the table foretag_kontaktervisadbrf2017 contains 0 or 1 row per user.
SELECT
brfbolagsverket.BrfNamn
, CASE WHEN L.Foretag_kontaktID IS NOT NULL THEN 'Lest' ELSE 'Inte lest' END AS NotificationRead
, brfextra.BrfId
, brfextra.Organisationsnr
, brfextra.Gatuadress
, brfextra.Ort
, brfextra.Lagenheter
, brfextra.ByggAr
, BrfHarFastighet.Fangdatum
FROM (((((
brfextra AS B
LEFT JOIN BrfHarFastighet ON brfextra.Organisationsnr = BrfHarFastighet.Organisationsnr)
LEFT JOIN brfkonkurs ON brfextra.Organisationsnr = brfkonkurs.Organisationsnr)
LEFT JOIN brfavford ON brfextra.Organisationsnr = brfavford.Organisationsnr)
LEFT JOIN brffusion ON brfextra.Organisationsnr = brffusion.Organisationsnr)
LEFT JOIN brflikvidation ON brfextra.Organisationsnr = brflikvidation.Organisationsnr)
LEFT JOIN brfbolagsverket ON brfextra.Organisationsnr = brfbolagsverket.Organisationsnr
LEFT JOIN foretag_kontaktervisadbrf2017 AS L ON L.Organisationsnr = B.Organisationsnr AND L.Foretag_kontaktID = 1247 -- This id probably needs to come from somewhere else, join in the users etc..
WHERE (((brfkonkurs.BolagetsStatusKod) Is Null) AND ((brfavford.BolagetsStatusKod) Is Null) AND ((brffusion.BolagetsStatusKod) Is Null) AND ((brflikvidation.BolagetsStatusKod) Is Null Or (brflikvidation.BolagetsStatusKod)=34))

Related

GROUP BY with HAVING but unrecognized table in MySQL

I have this query, and I am trying to split the answer column RES (that is divided by commas) into more rows (instead). But when I try to do that, the HAVING part is not working at all, and it's throwing: Unknow column.
This is the original query:
SELECT ad.ID_ANSWER as idRes
, IFNULL(c.NOMBRE_FACTURA,a.INTERVIEWED_NAME) AS nomPdv
, c.CODIGO
, q.`NAME` AS nombreEncuesta
, ad.ID_QUESTION AS idCue
, que.QUESTION
, GROUP_CONCAT(ad.ANSWER) AS RES
, a.LATITUDE
, a.LONGITUDE
, cm.DIRECCION
, c.NIT
, cm.NOMREPRESENTANTE
, cm.FECHA_NACIMIENTO
, a.ID_QUESTIONARY
, cm.TELEFONO, cm.FECHA_NACIMIENTO, cm.NITREPRESENTANTE,
CONCAT(cm.APELLIDO_PATERNO,' ',cm.APELLIDO_MATERNO,' ', cm.NOMBRES_CLIENTE) as RAZONSOCIAL, a.USUARIO_ID, a.FECHA_ID, R.NOMBRE AS RUTA, CASE WHEN D.NOMBRE IS NULL THEN DP.NOMBRE ELSE D.NOMBRE END AS DEPARTAMENTO, P.NOMBRE AS ENCUESTADOR
FROM VM_ANSWER AS a
JOIN VM_ANSWER_DETAIL ad
ON ad.ID_ANSWER = a.ID_ANSWER
JOIN VM_QUESTIONARY AS q
ON q.ID_QUESTIONARY = a.ID_QUESTIONARY
JOIN VM_QUESTION AS que
ON que.ID_QUESTION = ad.ID_QUESTION
JOIN VM_QUESTIONARY_RANGE AS qr
on qr.ID_QUESTIONARY = a.ID_QUESTIONARY
AND qr.OPERACION_ID = 1
JOIN AD_USUARIO U
ON U.USERNAME = a.USUARIO_ID
JOIN GL_PERSONA P
ON P.ID_PERSONA = U.ID_PERSONA
LEFT
JOIN (SELECT * FROM VP_VENDEDOR V GROUP BY V.ID_PERSONA) V ON V.ID_PERSONA = U.ID_PERSONA
LEFT JOIN VP_SUCURSAL S ON S.ID_SUCURSAL = V.ID_SUCURSAL
LEFT JOIN GL_DEPARTAMENTO D ON D.ID_DEPARTAMENTO = S.ID_DEPARTAMENTO
LEFT JOIN VP_CLIENTE AS c ON c.ID_CLIENTE = a.ID_CLIENT
LEFT JOIN VM_CLIENTE_MOVIL AS cm ON cm.ID_CLIENTE = c.ID_CLIENTE
LEFT JOIN GL_DEPARTAMENTO DP ON DP.ID_DEPARTAMENTO = cm.ID_CIUDAD
LEFT JOIN VM_RUTA_VENDEDOR RV ON RV.ID_VENDEDOR = V.ID_VENDEDOR AND RV.OPERACION_ID > 0
LEFT JOIN VM_RUTA R ON R.ID_RUTA = RV.ID_RUTA
WHERE a.OPERACION_ID = 1 AND qr.ID_BRANCH = 3 AND IF (61 = 0, TRUE, a.ID_QUESTIONARY = 61)
GROUP BY a.ID_QUESTIONARY,a.ID_ANSWER
ORDER BY a.ID_QUESTIONARY,a.ID_ANSWER
When I add the following code
LEFT JOIN GL_TIPO T ON T.ID_TIPO = que.ID_TYPE
WHERE a.OPERACION_ID = 1 AND qr.ID_BRANCH = 3 AND IF (61 = 0, TRUE, a.ID_QUESTIONARY = 61)
GROUP BY a.ID_QUESTIONARY,a.ID_ANSWER, ad.ID_ANSWER_DETAIL HAVING T.ID_TIPO=1012
ORDER BY a.ID_QUESTIONARY,a.ID_ANSWER
throws me the error of not recognized table T.ID_TIPO, but if I take off the HAVING word, the left join works normally.
this is the normal result, that as you can see in the column RES, it's divided by a comma when there is more than an answer:
I know it's complicated to understand, 1012 is a multi-select answer type from table GL_TIPO, and it's used in the table Question to define the type of it.
If you can help me to understand what I am doing wrong with the HAVING reserved word it would be awesome, but if you have any suggestion is also welcome too.
Try this:
GROUP BY a.ID_QUESTIONARY,a.ID_ANSWER, que.ID_TIPO=1012
This will put the questions with ID_TIPO=1012 into its own row, and all other ID_TIPO values will be grouped together. Both of these are nested within the ID_QUESTIONARY, ID_ANSWER groups.

SQL query returns column with data from another column

I have a table Notices connected to tables Likes and Comments. When I return the notices for a user I also create columns: number_of_likes, number_of_comments and liked_by_me. The query is working correctly when the user making the query hasn't liked a notice (liked_by_me = 0) . But if they have (liked_by_me = 1) the value I get for number_of_likes is wrong and is the same as number_of_comments.
Example:
1)
- liked by me = false
- likes = 1
- comments = 5
Returned values:
- liked_by_me = 0
- number_of_likes = 1
- number_of_comments = 5
2)
- liked by me = true
- likes = 2
- comments = 5
Returned values:
- liked_by_me = 1
- number_of_likes = 5
- number_of_comments = 5
Here is the query I am using:
SELECT notices.*
, count(comment.id) as number_of_comments
, count(like1.user_id) as number_of_likes
, like2.user_id IS NOT NULL AS liked_by_me
, boards.name as board_name
FROM notices
LEFT JOIN comments as comment
ON (comment.notice_id = notices.id)
LEFT JOIN likes as like1
ON (like1.notice_id = notices.id)
LEFT JOIN likes as like2
ON (like2.notice_id = notices.id
AND like2.user_id = $1)
LEFT JOIN boards
ON (boards.id = notices.board_id)
LEFT OUTER JOIN board_users
ON (board_users.board_id = notices.board_id)
WHERE board_users.user_id = $1
GROUP BY notices.id
, boards.name
, like2.user_id
, userId
Any help would be appreciated. I have been on this for hours and I don't think I will be able to find the problem.
Thanks!
Solution:
Here is the working query
SELECT notices.*,
(SELECT COUNT(user_id) from likes WHERE likes.notice_id = notices.id) AS number_of_likes,
(SELECT user_id IS NOT NULL from likes WHERE likes.notice_id = notices.id AND likes.user_id = $1) AS liked_by_me,
count(comments.id) as number_of_comments, boards.name as board_name
FROM notices LEFT JOIN comments ON (comments.notice_id = notices.id)
LEFT JOIN boards ON (boards.id = notices.board_id)
LEFT OUTER JOIN board_users ON (board_users.board_id = notices.board_id)
WHERE board_users.user_id = $1 GROUP BY notices.id, boards.name", user);
You will have to use subeselects.
Excellent article on this problem: The GROUPing pitfall
TL;DR: Basically, you have to realize, that all your comments and likes are being multiplicated by one another. Try to display the result of the query without the group clause to see, that duplicate likes/comments are being counted.
EDIT: I didn't test this, but it's how the query might look:
(that is if user can only like one notice once, otherwise you would have to group current user likes too)
SELECT
notices.*,
comments.number_of_comments,
likes.number_of_likes
current_user_likes.user_id IS NOT NULL AS liked_by_me
boards.name AS board_name
FROM notices
LEFT JOIN (
SELECT
COUNT(*) AS number_of_comments,
notice_id
FROM comments
GROUP BY notice_id
) AS comments ON comments.notice_id = notices.id
LEFT JOIN (
SELECT
COUNT(*) AS number_of_likes,
notice_id
FROM likes
GROUP BY notice_id
) AS likes ON likes.notice_id = notices.id
LEFT JOIN likes AS current_user_likes
ON current_user_likes.notice_id = notices.id
AND current_user_likes.user_id = $1
LEFT JOIN boards ON boards.id = notices.board_id
INNER JOIN board_users
ON board_users.board_id = notices.board_id
AND board_users.user_id = $1;

Adding a subquery to a join

I've been using the following join, to pull rows of users whom have volunteered for various project positions.
SELECT p.id, up.position_id, title, max_vol, current_datetime, IF(up.id IS NULL, "0", "1") volunteered
FROM positions AS p
LEFT JOIN users_positions AS up
ON p.id = up.position_id
AND up.user_id = 1
AND up.calendar_date = '2016-10-03'
WHERE
p.project_id = 1
AND p.day = 1
...but in a change of functionality, I have to now account for the date of the latest edit to a project. In another query, I solved it like so
SELECT *
FROM positions
WHERE
current_datetime = (SELECT MAX(current_datetime)
FROM positions
WHERE
project_id = 1 AND day = 1)
Which works fine, but now I have to also incorporate the return of rows which match the latest datetime in the left join query.
I just can't seem to wrap my head around it. Any suggestions? Thanks.
Use a sub query, like this:
SELECT
p.id,
up.position_id,
title,
max_vol,
current_datetime,
IF(up.id IS NULL,
"0",
"1") volunteered
FROM
( SELECT
*
FROM
positions
WHERE
current_datetime = (
SELECT
MAX(current_datetime)
FROM
positions
WHERE
project_id = 1
AND day = 1
)
) AS p
LEFT JOIN
users_positions AS up
ON p.id = up.position_id
AND up.user_id = 1
AND up.calendar_date = '2016-10-03'
WHERE
p.project_id = 1
AND p.day = 1

MySQL Join three table if one table no record

$numQuery1 = "
SELECT d.*
, r.*
, AVG(c.on_time)+AVG(c.friendly)+AVG(c.language_skills)+AVG(c.professional) ranking
FROM comment c
LEFT
JOIN driver d
ON d.userid = c.driver_id
LEFT
JOIN driver_rental r
ON r.email = d.email
WHERE
(
$driver_rental IS NOT NULL
AND $driver_rental != ''
AND car_type_1 >= $_SESSION[car_type_1]
)
OR car_type_2>=$_SESSION[car_type_1]);
";
if the comment table have no driver_id record, the result is null, can I ignore comment table but in select statement cannot without it?
$numQuery1 = "SELECT driver.*, driver_rental.*, avg(comment.on_time)+avg(comment.friendly)+avg(comment.language_skills)+avg(comment.professional) as ranking
FROM comment
LEFT JOIN driver
ON
driver.userid = comment.driver_id
RIGHT JOIN driver_rental
ON
driver.email = driver_rental.email
WHERE
($driver_rental IS NOT NULL AND $driver_rental != '') AND (car_type_1>=$_SESSION[car_type_1] OR car_type_2>=$_SESSION[car_type_1])";
The idea is to not stress on driver table in either join. SO instead of second left join use right join with driver_rental

MySQL - WHERE every value is IN

The following query selects all workunts where the inputs are "done" (subquery on line 7). This works fine... when there is only one input. How can I change this so that it requires every input to be IN that set returned by the subquery, not just one of the inputs to be present?
SELECT workunits.ID
FROM workunits
LEFT JOIN workunitInputs ON workunits.ID = workunitInputs.workunitID
WHERE workunits.ID NOT IN (SELECT workunitID FROM jobworkunitassoc)
AND (
workunitInputs.inputID IN (
SELECT workunitOutputs.outputID
FROM workunitOutputs
LEFT JOIN workunits ON workunitOutputs.workunitID = workunits.ID
LEFT JOIN jobworkunitassoc ON workunits.ID = jobworkunitassoc.workunitID
LEFT JOIN jobs ON jobworkunitassoc.jobID = jobs.ID
WHERE jobs.done = 1
)
OR workunitInputs.inputID IS NULL
)
GROUP BY workunits.ID
Thanks, Istvan.
Change that clause to:
AND (
workunitInputs.inputID NOT IN (
SELECT workunitOutputs.outputID
FROM workunitOutputs
LEFT JOIN workunits ON workunitOutputs.workunitID = workunits.ID
LEFT JOIN jobworkunitassoc ON workunits.ID = jobworkunitassoc.workunitID
LEFT JOIN jobs ON jobworkunitassoc.jobID = jobs.ID
WHERE jobs.done != 1
)
This is based on the logical tautology: All X in Y === No X in !Y
This query works for me, though it may not be the best solution:
http://pastebin.com/g9qBjQGU