Reputation:
I have the following tables:
scenes
------
scene_id
title
video_url
modified_at
uuid
likes
----
scene_id
uuid
active
users
-----
uuid
username
Problem 1: I want to get the number of likes for scenes,scene_id, author in descending order; please note that we need to count just those likes which are active in likes table!
My try:
SELECT s.scene_id,s.video_url,s.title,s.uuid, u.username as author,s.data,count(l.active) as likes
FROM scenes s
left join likes l
on l.scene_id = s.scene_id
join users u
on u.uuid = s.uuid
where s.video_url IS not NULL
group by s.scene_id
order by modified_at DESC;
But this is counting all of the likes, irrespective whether it is active or not! I dont know how I can add that one in my query!
Problem 2:
Also I wonder whether it is possible to add another column in the result set which shows a specific user (the uuid can be passed and used in where clause) has liked each scene in the result set or not? Is it possible to have this result in just one query?
Please let me know if you need more clarification!
Thanks!
Upvotes: 0
Views: 65
Reputation: 108480
Adding the predicate on the active
column is straightforward; it just depends on how that's represented... is that an integer type column, using 0 and/or NULL to indicate that it's "inactive", and a 1 and/or any positive integer to indicate that it's active
?
To get "number of likes for scenes,scene_id, author in descending order", you could do something like this:
SELECT COUNT(l.scene_id) AS cnt_likes
, s.scene_id AS scene_id
, a.username AS author
FROM scenes s
LEFT
JOIN users a
ON a.uuid = s.uuid
LEFT
JOIN likes l
ON l.scene_id = s.scene_id
AND l.active+0
GROUP BY s.scene_id
ORDER BY cnt_likes DESC, s.scene_id DESC, a.username DESC
If the column active
is character type, and you are using a value of "yes" to indicate a like is active, you'd need to change the predicate,
Replace:
AND l.active+0
With:
AND l.active = 'yes'
etc.
For the second question, identifying the users that have 'active likes' for a scene
(i.e. rows included in the aggregate), that's problematic, because there can be multiple users with a like for a scene... which of those users do we identify to return, just any one of them, all of them?... i just re-read your question more carefully. You want to know if one particular identified user has a like
for the scene.
Just test if the uuid on the like row is equal to the value you are looking for, and return a 0 or 1, and then get the MAX() of that.
e.g.
SELECT COUNT(l.scene_id) AS cnt_likes
, s.scene_id AS scene_id
, a.username AS author
, MAX(l.uuid = 'auser') AS liked_by_user
FROM scenes s
LEFT
JOIN users a
ON a.uuid = s.uuid
LEFT
JOIN likes l
ON l.scene_id = s.scene_id
AND l.active+0
GROUP BY s.scene_id
ORDER BY cnt_likes DESC, s.scene_id DESC, a.username DESC
FOLLOWUP
The expression
MAX(l.uuid = 11 )
can return 1, 0 or NULL. (1 would be equivalent to boolean TRUE, 0 to boolean false, and a NULL would be unknown, or in this case, we'd treat it as also being FALSE.
In MySQL, integers can be treated as booleans, and booleans are handled as integers.
To return strings 'true' or 'false', you could use an IF() function
IF(MAX(l.uuid = 11 ), 'true', 'false')
Upvotes: 1