This query runs fine and gives me an output like this:
[(1, 9), (2, 12), (4, 14), (6, 14)]
query = """
SELECT users.id,
count(tasks.userId)
FROM users
LEFT JOIN tasks ON users.id = tasks.userId
WHERE tasks.completed = FALSE
GROUP BY users.id
"""
However, when I add another left join, it does not give me accurate results:
query = """
SELECT users.id,
count(tasks.userId), count(songs.userId)
FROM users
LEFT JOIN tasks ON users.id = tasks.userId
LEFT JOIN songs ON users.id = songs.userId
WHERE tasks.completed = FALSE
GROUP BY users.id
"""
The result should look like this:
[(1, 9, 10), (2, 12, 10), (4, 14, 10), (6, 14, 10)]
but instead, my result looks like this:
[(1, 90, 90), (2, 120, 120), (4, 140, 140), (6, 140, 140)]
which looks like the value of tasks x 10
as both, count(tasks) and count(song)
what am I missing out on?
The idea of count(tasks.userId)
was to find the number of tasks where the userId matched.
CodePudding user response:
Aggregate separately in tasks
and songs
and then join users
to the results of the aggregations:
SELECT u.id,
COALESCE(t.count_tasks, 0) count_tasks,
COALESCE(s.count_songs, 0) count_songs
FROM users u
LEFT JOIN (
SELECT userId, COUNT(*) count_tasks
FROM tasks
WHERE completed = FALSE
GROUP BY userId
) t ON u.id = t.userId
LEFT JOIN (
SELECT userId, COUNT(*) count_songs
FROM songs
GROUP BY userId
) s ON u.id = s.userId;
I'm not sure if you actually want LEFT
joins (at least for the table tasks
), because in your code, the 1st query that you say returns what you expect, although it contains a LEFT
join, the join is actually an INNER
join because the condition WHERE tasks.completed = FALSE
returns only the matching rows.