Reputation: 21553
I have this SQL statement:
SELECT
(CASE
WHEN EXISTS
(SELECT *
FROM votes
WHERE votes.user_id = 0
AND votes.post_id = posts.id
AND votes.vote = 0) THEN 0
WHEN EXISTS
(SELECT *
FROM votes
WHERE votes.user_id = 0
AND votes.post_id = posts.id
AND votes.vote = 1) THEN 1
ELSE 2
END) AS vote_by_me ,
posts.*
FROM `posts`
Is there a way I can do this in a DRY manner? Both select statements are almost the same, would be nice to factor them out some way.
Thanks
Upvotes: 3
Views: 49
Reputation: 726559
Yes, you can select votes.vote
directly, like this:
SELECT
COALESCE(
(
SELECT MIN(votes.vote)
FROM votes
WHERE votes.user_id = 0 AND votes.post_id = posts.id
AND votes.vote in (0, 1)
GROUP BY votes.user_id, votes.post_id
)
, 2
) AS vote_by_me
, posts.*
FROM `posts
If a post cannot have multiple votes by the same user, you could eliminate the GROUP BY
, like this:
SELECT
COALESCE(
(
SELECT votes.vote
FROM votes
WHERE votes.user_id = 0 AND votes.post_id = posts.id AND votes.vote in (0, 1)
)
, 2
) AS vote_by_me
, posts.*
FROM `posts
Upvotes: 1
Reputation: 6202
SELECT
(CASE
WHEN EXISTS
(SELECT *
FROM votes
WHERE votes.user_id = 0
AND votes.post_id = posts.id
AND votes.vote IN (0,1) )THEN votes.vote
ELSE 2
END) AS vote_by_me ,
posts.*
FROM `posts`
Upvotes: 1
Reputation: 1269743
This would seem to simplify the query:
SELECT (CASE WHEN v.votes0 > 0 THEN 0
WHEN v.votes1 > 0 THEN 1
ELSE 2
END) AS vote_by_me,
p.*
FROM posts p left outer join
(select v.post_id, sum(v.vote = 1) as vote1, sum(v.vote = 0) as vote0
from votes v
where v.user_id = 0
group by v.post_id
) v
on p.post_id = v.post_id;
The bad news is that if you have an index on votes(user_id, post_id, votes)
then your original form will probably have better performance.
EDIT:
The following formulation might perform well and sort-of simplify the query:
SELECT (CASE (SELECT min(vote)
FROM votes
WHERE votes.user_id = 0 AND
votes.post_id = posts.id
)
WHEN 0 then 0
WHEN 1 then 1
ELSE 2
END) AS vote_by_me,
posts.*
FROM `posts`;
Upvotes: 1