Reputation: 24305
I can't figure out how to SUM
up and down votes on a certain item while also returning whether or not a given user voted on this item.
Here's my Votes table:
item_id vote voter_id
1 -1 joe
1 1 bob
1 1 tom
3 1 bob
For item_id=1
here's the data I want to show:
If Joe
is looking at the page:
total up votes: 2
total down votes: 1
my_vote: -1
Bob
:
total up votes: 2
total down votes: 1
my_vote: 1
Here's my code:
SELECT MAX(CASE WHEN voter_id = 'joe' and vote=1 THEN 1
WHEN voter_id = 'joe' and vote='-1' THEN -1
ELSE 0 END)
AS my_vote, item_id, sum(vote=1) yes, sum(vote='-1') no
FROM Votes
WHERE item_id=1
The issue is that my_vote=0
if I use the MAX
function and vote=-1
(Joe's scenario). Similarly, my_vote=0
if I use the MIN function and the vote=1
(Bob's scenario).
Thoughts?
Upvotes: 1
Views: 7902
Reputation: 326
My answer's pretty much the same, but for those of us who love stored procs I've cleaned it up a little:
declare p_item_id int;
declare p_voter_id varchar(10);
select
sum(vote = 1) as TotalUpVotes
, sum(vote = -1) as TotalDownVotes
, sum(vote) as TotalScore
, sum(case when p_voter_id = voter_id then vote else 0 end) as my_vote
from Votes v
where p_item_id = v.item_id
Upvotes: 1
Reputation: 2654
You can use something like this
select 'total up votes' as descr, count(*) as num from Votes where item_id=1 and vote=1 union all select 'total down votes', count(*) from Votes where item_id=1 and vote=-1 union all select 'my_vote' as descr, vote from Votes where item_id=1 and voter_id = 'joe'
Upvotes: 0
Reputation: 86715
SELECT
item_id,
MAX(CASE WHEN voter_id = 'Joe' THEN vote ELSE NULL END) AS my_vote,
sum(vote= 1) AS yes_votes,
sum(vote=-1) AS no_votes
FROM
Votes
WHERE
item_id = 1
GROUP BY
item_id
Or, possibly more flexible...
SELECT
Votes.item_id,
MAX(CASE WHEN Users.user_id IS NOT NULL THEN Votes.vote ELSE NULL END) AS my_vote,
sum(Votes.vote= 1) AS yes_votes,
sum(Votes.vote=-1) AS no_votes
FROM
Votes
LEFT JOIN
Users
ON Users.user_id = Votes.voter_id
AND Users.user_id = 'Joe'
WHERE
Votes.item_id = 1
GROUP BY
Votes.item_id
Upvotes: 3
Reputation: 263723
You can use correlated subquery to get the user vote and assuming that the user can only vote once per item_id
.
SELECT SUM(vote = 1) totalUpVotes,
SUM(vote = -1) totalDownVotes,
(SELECT MAX(vote)
FROM votes b
WHERE a.item_id = b.item_id AND
b.voter_id = 'joe') my_vote
FROM votes a
WHERE item_id = 1
Upvotes: 1