I have a two tables - items and its states. Each item has only one state. I need to get list of states with counted items of that state, but only from certain ower. When I remove WHERE
part I get list of all states, but with it I get only some of states, because there are not at all same states used in items with owner no.7
. How to get all of states even if it's amount is zero?
Only solution I have is use subquery instead of COUNT(i.id)
, but that would be much more slower and I am afraid of performance.
My tables:
ID STATE NAME
== ==========
1 New
2 Used
3 Archived
4 Unknown
ID STATE ITEM NAME OWNER
== ===== ========= =====
1 1 ABC 7
2 2 DEF 6
3 3 GHI 7
4 1 JKL 7
My query:
SELECT
s.id,
s.name,
COUNT(i.id) AS count
FROM
b_items_states s
LEFT JOIN
b_items i ON i.state = s.id
WHERE
i.owner = 7
GROUP BY
s.id
My result:
ID NAME COUNT
== ==== =====
1 New 2
3 Archived 1
My expected result:
ID NAME COUNT
== ==== =====
1 New 2
2 Used 0
3 Archived 1
4 Unknown 0
Move the filtering condition inside the JOIN, as in:
SELECT
s.id,
s.name,
COUNT(i.id) AS count
FROM
b_items_states s
LEFT JOIN
b_items i ON i.state = s.id AND i.owner = 7
GROUP BY
s.id
If you place the filtering condition in a WHERE
statement, you are implicitly converting the outer join into an inner join, without even noticing.