Reputation: 53
I have this:
SELECT
posts.id,
(SELECT COUNT(*) FROM votes WHERE votes.post = posts.id) AS votesCount,
(SELECT SUM(vote) FROM votes WHERE votes.post = posts.id) AS votesUp
FROM posts WHERE posts.id = 1
How do i get the difference between votesCount and votesUp without doing other SELECT? Something like:
SELECT
posts.id,
(SELECT COUNT(*) FROM votes WHERE votes.post = posts.id) AS votesCount,
(SELECT SUM(vote) FROM votes WHERE votes.post = posts.id) AS votesUp,
votesCount - votesUp AS votesDown
FROM posts WHERE posts.id = 1
Is it possible, or do i have to call another SELECT anyway? Thanks.
Btw, sorry for my bad english.
Upvotes: 4
Views: 66
Reputation: 33437
Your sub queries don't quite make sense. Typically you want to use subqueries as a last resort in preference of joins. For example:
SELECT
posts.id, COUNT(votes.*) AS votesCount, SUM(vote) AS votesUp
FROM posts
LEFT JOIN votes ON votes.post = posts.id
WHERE
posts.id = 1
GROUP BY posts.id
This also makes it easier to do the subtraction, though it does unfortunately require a bit of repetition (aliases cannot be used in subsequent columns :/):
SELECT
posts.id, COUNT(votes.*) AS votesCount, SUM(vote) AS votesUp,
COUNT(votes.id) - SUM(vote) AS votesDown
FROM posts
LEFT JOIN votes ON votes.post = posts.id
WHERE
posts.id = 1
GROUP BY posts.id
Upvotes: 1
Reputation: 11
Not even another nested SELECT?
SELECT
posts.id,
(SELECT COUNT(*) FROM votes WHERE votes.post = posts.id) AS votesCount,
(SELECT SUM(vote) FROM votes WHERE votes.post = posts.id) AS votesUp
(SELECT SUM(CASE WHEN vote=0 THEN 1 ELSE 0 END) FROM votes WHERE votes.post = posts.id) AS votesDown
FROM posts WHERE posts.id = 1
Upvotes: -3
Reputation: 700302
I would suggest that you join in the votes instead of using subqueries, then you can easily reuse the aggregates:
select
p.id,
count(v.post) as votesCount,
sum(v.vote) as votesUp,
count(v.post) - sum(v.vote) as votesDown
from
posts p
left join votes v on v.post = p.id
where
p.id = 1
group by
p.id
Upvotes: 3