Odd MySQL behavior with LEFT JOIN
I've got a weird question. I have a user table where each user has a unique user id. Users are able to post comments (tips) which are saved to a different table, each comment row also has a unique ID and also contains the user ID of the user that posted it. Finally, other users are able to vote on the comments. Votes are stored in another table along with the user ID of the person that voted, and the comment ID of the comment being voted on (no unique ID).
I calculate a person's rating as the number of up votes minus the number of down votes, so 4 up and 2 down would result in a rating of 2, simple. I want to have a member list that is sortable by a person's rating, but I'm having a bit of an issue.
I use COUNT() and CASE to determine the number of up and down votes:
(COUNT(CASE WHEN V.vote = 1 THEN 1 ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 1 ELSE NULL END)) AS 'rating',
This works when I supply a single User ID to the query, in the WHERE clause, WHERE user_id = 1. However, I want to get a list of all members and their ratings, and that's where the problem happens. My query:
SELECT DISTINCT
U.user_id,
(COUNT(CASE WHEN V.vote = 1 THEN 1 ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 1 ELSE NULL END)) AS 'rating',
username
FROM users U
LEFT JOIN tips T ON U.user_id = T.user_id
LEFT JOIN votes V ON T.tip_id = V.tip_id
Basically, this should find all rows in the votes where the tip_id is equal to the tip_id in the tips table, then all rows in the tips table where the user_id is equal to the user_id in the users table. The problem I'm having is that I only get a single row returned, even though there are 83 rows in the users table. There are 287 rows in the votes table, with 257 up votes and 30 down votes. This single row that I get has a rating of 227 (which is 257-30), which means that ALL the rows in the votes table are being counted, not just those for the specific user_id that I'm looking for. I want to get the number of up- and down-votes that each user has had for all of his or her tips.
Basically, for every user_id in the users table, it should find all of the tip_id's for that user id, then all votes for those tip_id's.
Is this not possible, or am I missing something horribly obvious?
EDIT:开发者_开发问答 I should note that if I remove the COUNT() line completely, then the query works, returns the proper number of rows...it just doesn't have the vote information.
SELECT
U.user_id,
(COUNT(CASE WHEN V.vote = 1 THEN 1 ELSE NULL END)-COUNT(CASE WHEN V.vote = 0 THEN 1 ELSE NULL END)) AS 'rating',
username
FROM users U
LEFT JOIN tips T ON U.user_id = T.user_id
LEFT JOIN votes V ON T.tip_id = V.tip_id
GROUP BY U.user_id, rating, username
I didn't test it. But i think you're missing the group by clause.
精彩评论