For my application I have a topic table and a vote table. The vote options are -1, 0, and 1. I’m trying to find the amount of times each topic was voted -1 and 1.
So to find out, I am doing many subqueries, each of which uses the algorithm of find total number of -1 or 1 votes and then divide by the total number of votes
.
Unfortunately, what I came up with is very slow. In part because I am calculating the count twice, but I’m not sure if it’s possible to reference it from the outer query.
Can the performance of this be improved?
x
SELECT title,
(SELECT COUNT(vote)::float8 FROM vote WHERE topic_id = v1.topic_id AND vote_choice = -1)
/ (SELECT COUNT(vote)::float8 FROM vote WHERE topic_id = v1.topic_id) as lp,
(SELECT COUNT(vote)::float8 FROM vote WHERE topic_id = v1.topic_id AND vote_choice = 1)
/ (SELECT COUNT(vote)::float8 FROM vote WHERE topic_id = v1.topic_id) as rp
FROM topic
JOIN vote v1 ON topic.id = v1.topic_id
GROUP BY v1.topic_id, topic.title;
Advertisement
Answer
I would use FILTER
instead of correlated subqueries:
SELECT
title,
1.0 * COUNT(*) FILTER(WHERE vote_choice = -1) / COUNT(*) as lp,
1.0 * COUNT(*) FILTER(WHERE vote_choice = 1) / COUNT(*) as rp
FROM topic
JOIN vote v1 ON topic.id = v1.topic_id
GROUP BY v1.topic_id, topic.title;