Here is my table layout:
What I would like to do:
- Count the number of
votes
for eachsongID
in a particular room (passed in as a parameter). - Find out if the userID has at least one vote for a song in a particular room. UserID is also passed in as a parameter.
- An extension of the two above. If there are no votes for a song, I would like to return 0 for those entries.
What I have:
select a.SongID, count(*) as voteCount, b.UserID
from votes a left join votes b
on a.songID = b.songID
and b.RoomID = 178
and b.UserID = 71
where a.RoomID = 178
group by a.SongID, b.UserID
(feel free to use those RoomID
and UserID
numbers in examples)
The above SQL statement does 1 and 2 but not 3. Is there any way to extend it to do 3? It would be nice to get all this done in a single query. Right now it returns all songs that have a vote, the number of votes and if the UserID
in question has voted (null otherwise). Thanks in advance.
Just to clarify a bit, currently, this statement will only output songs with entries in the votes
table, I’m trying to modify it to include songs that do not have entries in the votes
table (that is, to include all songs in Select SongID from songs where RoomID = 178
). Also keeping in mind everything is room-specific. Songs are matched to a certain room by their SongID
.
Here is my song table for example:
+--------+--------+
| SongID | RoomID |
+--------+--------+
| 2835 | 178 |
| 2836 | 178 |
| 2837 | 178 |
| 2838 | 178 |
| 2839 | 178 |
| 2840 | 178 |
| 2841 | 178 |
| 2842 | 178 |
| 2843 | 178 |
| 2844 | 178 |
| 2845 | 178 |
| 2846 | 178 |
| 2847 | 178 |
| 2848 | 178 |
+--------+--------+
Here is the votes:
+--------+--------+--------+
| SongID | UserID | RoomID |
+--------+--------+--------+
| 2835 | 71 | 178 |
| 2836 | 71 | 178 |
| 2837 | 71 | 178 |
| 2838 | 71 | 178 |
| 2839 | 71 | 178 |
| 2840 | 71 | 178 |
| 2841 | 71 | 178 |
| 2842 | 71 | 178 |
+--------+--------+--------+
And finally, the result of the query I have so far:
Only the first 7 songs have votes and only those are returned. I would like to modify this query to include ALL songs that are in the room, even if they have no votes (and return the vote count as 0 or null).
+--------+-----------+--------+
| SongID | voteCount | UserID |
+--------+-----------+--------+
| 2835 | 1 | 71 |
| 2836 | 1 | 71 |
| 2837 | 1 | 71 |
| 2838 | 1 | 71 |
| 2839 | 1 | 71 |
| 2840 | 1 | 71 |
| 2841 | 1 | 71 |
+--------+-----------+--------+
Advertisement
Answer
I believe your query might look like this
SELECT s.SongID,
COALESCE(v.allVotes, 0) allVotes,
COALESCE(v.userVotes, 0) userVotes
FROM songs s LEFT JOIN
(
SELECT SongId,
COUNT(*) allVotes,
SUM(CASE WHEN UserID = 71 THEN 1 ELSE 0 END) userVotes
FROM votes
WHERE RoomID = 178
GROUP BY SongID
) v
ON s.songID = v.songID
WHERE s.RoomID = 178
Here is SQLFiddle demo