Съединенията се обработват отляво надясно (освен ако скоби не диктуват друго). Ако LEFT JOIN
(или просто JOIN
, подобен ефект) три хранителни стоки за един потребител получавате 3 реда (1 x 3 ). Ако след това се присъедините към 4 рибни пазари за един и същ потребител, получавате 12 (3 x 4 ) редове, умножаване предишният брой в резултата, а не добавянето към него, както може би сте се надявали.
По този начин се умножават посещенията както за хранителни стоки, така и за рибни пазари.
Можете да го накарате да работи по следния начин:
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;
За да получите обобщени стойности за един или няколко потребители, корелирани подзаявки като @Vince, предоставени са просто добре. За цяла таблица или големи части от нея е (много) по-ефективно да се агрегират n-таблиците и да се присъединят към резултата веднъж . По този начин също не се нуждаем от друг GROUP BY
във външната заявка.
grocery_visits
и fishmarket_visits
са NULL
за потребители без никакви свързани записи в съответните таблици. Ако имате нужда от 0
вместо това (или произволно число), използвайте COALESCE
във външния SELECT
:
SELECT u.id
, u.account_balance
, COALESCE(g.grocery_visits , 0) AS grocery_visits
, COALESCE(f.fishmarket_visits, 0) AS fishmarket_visits
FROM ...