Joins bearbetas från vänster till höger (om inte parentesen anger något annat). Om du LEFT JOIN
(eller bara JOIN
, liknande effekt) tre matvaror till en användare får du 3 rader (1 x 3 ). Om du sedan går med i 4 fiskmarknader för samma användare får du 12 (3 x 4 ) rader, multiplicera föregående räkning i resultatet, inte läggande till det, som du kanske har hoppats på.
Därmed multipliceras besöken för både livsmedel och fiskmarknader.
Du kan få det att fungera så här:
SELECT u.id
, u.account_balance
, g.grocery_visits
, f.fishmarket_visits
FROM users u
LEFT JOIN (
SELECT user_id, count(*) AS grocery_visits
FROM grocery
GROUP BY user_id
) g ON g.user_id = u.id
LEFT JOIN (
SELECT user_id, count(*) AS fishmarket_visits
FROM fishmarket
GROUP BY user_id
) f ON f.user_id = u.id
ORDER BY u.id;
För att få aggregerade värden för en eller ett fåtal användare, korrelerade underfrågor som @Vince förutsatt är bara bra. För en hel tabell eller större delar av den är det (mycket) mer effektivt att aggregera n-tabellerna och gå med i resultatet en gång . På så sätt behöver vi inte heller en annan GROUP BY
i den yttre frågan.
grocery_visits
och fishmarket_visits
är NULL
för användare utan relaterade poster i respektive tabell. Om du behöver 0
istället (eller valfritt godtyckligt nummer), använd COALESCE
i den yttre SELECT
:
SELECT u.id
, u.account_balance
, COALESCE(g.grocery_visits , 0) AS grocery_visits
, COALESCE(f.fishmarket_visits, 0) AS fishmarket_visits
FROM ...