Reputation: 937
I have a simple schema with a table for the posts
and two tables to track views
and upvotes
:
CREATE TABLE posts (
id integer NOT NULL PRIMARY KEY,
title VARCHAR(255) NOT NULL
);
CREATE TABLE views (
post_id integer,
value integer
);
CREATE TABLE upvotes (
post_id integer,
value integer
);
Please note that the tuples in views
and upvotes
represent a generic number of views and upvotes. I want to aggregate the posts, showing the total amount of views and upvotes.
I thought it'd be simple, but unfortunately I'm failing.
This is my query:
SELECT posts.title,
SUM(views.value) AS views,
SUM(upvotes.value) AS upvotes
FROM posts
LEFT OUTER JOIN views ON (posts.id = views.post_id)
LEFT OUTER JOIN upvotes ON (posts.id = upvotes.post_id)
GROUP BY posts.id;
I understand why it's failing, but I really don't understand how to do it. If I need to run two different queries and aggregate the result on the application level, I'm fine with that. I just want to understand if it's possible with a single query
I created a sqlfiddle with my test case.
PS: I manage to make it work using just a single generic table to track events, but I'd like to keep the table separated. sqlfiddle here.
Upvotes: 2
Views: 144
Reputation: 26784
Do a JOIN between 2 separate selects
SELECT * FROM(SELECT posts.title,
SUM(views.value) AS views
FROM posts
LEFT OUTER JOIN views ON (posts.id = views.post_id)
GROUP BY posts.id)as x
JOIN(
SELECT posts.title,
SUM(upvotes.value) AS upvotes
FROM posts
LEFT OUTER JOIN upvotes ON (posts.id = upvotes.post_id)
GROUP BY posts.id)as y on x.title=y.title
Upvotes: 1
Reputation: 263683
You can safely calculate the values in a subquery. This will avoid you from summing up duplicate value leading you to an invalid result.
SELECT p.id,
p.title,
COALESCE(v.totalView, 0) totalView,
COALESCE(u.totalUpvote, 0) totalUpvote
FROM posts p
LEFT JOIN
(
SELECT post_id,
SUM(v.value) totalView
FROM views v
GROUP BY post_id
) v ON p.id = v.post_ID
LEFT JOIN
(
SELECT post_id,
SUM(u.value) totalUpvote
FROM upvotes u
GROUP BY post_id
) u ON p.ID = u.post_ID
Upvotes: 4