Les jointures sont traitées de gauche à droite (sauf si les parenthèses dictent le contraire). Si vous LEFT JOIN
(ou simplement JOIN
, effet similaire) trois courses à un utilisateur vous obtenez 3 rangées (1 x 3 ). Si vous rejoignez ensuite 4 poissonneries pour le même utilisateur, vous en obtenez 12 (3 x 4 ) lignes, multiplication le décompte précédent dans le résultat, et non l'ajout comme vous l'auriez peut-être espéré.
Multipliant ainsi les visites d'épiceries et de poissonneries.
Vous pouvez le faire fonctionner comme ceci :
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;
Pour obtenir des valeurs agrégées pour un ou quelques utilisateurs, sous-requêtes corrélées comme @Vince fourni sont très bien. Pour une table entière ou une grande partie de celle-ci, il est (beaucoup) plus efficace d'agréger les n-tables et de les joindre au résultat une fois . De cette façon, nous n'avons pas non plus besoin d'un autre GROUP BY
dans la requête externe.
grocery_visits
et fishmarket_visits
sont NULL
pour les utilisateurs sans aucune entrée associée dans les tables respectives. Si vous avez besoin de 0
à la place (ou n'importe quel nombre arbitraire), utilisez COALESCE
dans le SELECT
extérieur :
SELECT u.id
, u.account_balance
, COALESCE(g.grocery_visits , 0) AS grocery_visits
, COALESCE(f.fishmarket_visits, 0) AS fishmarket_visits
FROM ...