Sprzężenia są przetwarzane od lewej do prawej (chyba że nawiasy wskazują inaczej). Jeśli LEFT JOIN
(lub po prostu JOIN
, podobny efekt) trzy artykuły spożywcze na jednego użytkownika otrzymujesz 3 rzędy (1 x 3 ). Jeśli następnie dołączysz do 4 targów rybnych dla tego samego użytkownika, otrzymasz 12 (3 x 4 ) wiersze, mnożenie poprzednia liczba w wyniku, a nie dodawanie do niego, jak mogłeś mieć nadzieję.
W ten sposób zwielokrotni się wizyty w sklepach spożywczych i rybnych.
Możesz sprawić, by działał tak:
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;
Aby uzyskać zagregowane wartości dla jednego lub kilku użytkowników, skorelowane podzapytania jak pod warunkiem @Vince są w porządku. W przypadku całej tabeli lub jej głównych części (znacznie) efektywniej jest zagregować n-tabel i połączyć z wynikiem raz . W ten sposób nie potrzebujemy również kolejnej GROUP BY
w zewnętrznym zapytaniu.
grocery_visits
i fishmarket_visits
są NULL
dla użytkowników bez żadnych powiązanych wpisów w odpowiednich tabelach. Jeśli potrzebujesz 0
zamiast tego (lub dowolnej liczby), użyj COALESCE
w zewnętrznym SELECT
:
SELECT u.id
, u.account_balance
, COALESCE(g.grocery_visits , 0) AS grocery_visits
, COALESCE(f.fishmarket_visits, 0) AS fishmarket_visits
FROM ...