mySQL Query design - calculating a vote score for multiple content items
I have a content items table structured like
| contentid | message | categoryid | userid | dateadded | etc..
15 foo bar 3 4 somedate
16 more foo bar 3 4 somedate
16 foo stuff 3 4 somedate
and a votes table, where direction = 1 = an up vote, and = 2 being a down vote.
| voteid | contentid | userid | direction | dateadded
7 15 4 1 some date
8 15 6 1 some date
9 15 17 2 some date
And I'd like to select a set of content items, having an additional column on the end with its calculated score based on the votes in the votes table.
Previously, I had a 'score' column attached to the content table, and 开发者_如何学JAVAeach time a vote was cast, it would update its score. This was done so I wouldnt have to have a more complex query to calculate scores on each SELECT, but I'd like to change this now.
This votes table was designed a while ago, so if changing all the votes values to something other than 1 or 2 (perhaps -1 for a downvote) would make it easier, I will update the entire table.
What would the query be to pull all content items, each with a score in a calculated column?
Assuming the vote "direction" represents up and down votes:
SELECT i.contentid,
SUM(CASE WHEN v.direction = 1 THEN 1
WHEN v.direction = 2 THEN -1
ELSE 0 END) AS Votes
FROM items i
LEFT JOIN votes v
ON i.contentid = v.contentid
GROUP BY i.contentid
HAVING SUM(CASE WHEN v.direction = 1 THEN 1
WHEN v.direction = 2 THEN -1
ELSE 0 END) > -3
SELECT
items.*,
SUM(direction = 1) - SUM(direction = 2) AS score
FROM items
LEFT JOIN votes USING (contentid)
GROUP BY contentid
The reason this works is because a true comparison evaluates to 1
and a false one to 0
.
精彩评论