sql >> Databáze >  >> RDS >> PostgreSQL

Dvě SQL LEFT JOINS poskytují nesprávný výsledek

Spojení se zpracovávají zleva doprava (pokud závorky neurčují jinak). Pokud jste LEFT JOIN (nebo stačí JOIN , podobný efekt) tři potraviny jednomu uživateli získáte 3 řádky (1 x 3 ). Pokud se poté připojíte ke 4 rybím trhům pro stejného uživatele, získáte 12 (3 x 4 ) řádků, násobení předchozí počet ve výsledku, nikoli přidání k tomu, jak jste možná doufali.
Tím se znásobí návštěvnost obchodů s potravinami i rybích trhů.

Můžete to udělat takto:

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;

Chcete-li získat souhrnné hodnoty pro jednoho nebo několik uživatelů, korelované dílčí dotazy jako @Vince poskytnuté jsou v pořádku. Pro celou tabulku nebo její hlavní části je (mnohem) efektivnější agregovat n-tabulek a připojit se k výsledku jednou . Tímto způsobem také nepotřebujeme další GROUP BY ve vnějším dotazu.

grocery_visits a fishmarket_visits jsou NULL pro uživatele bez souvisejících položek v příslušných tabulkách. Pokud potřebujete 0 místo toho (nebo libovolné libovolné číslo) použijte COALESCE ve vnějším SELECT :

SELECT u.id
     , u.account_balance
     , COALESCE(g.grocery_visits   , 0) AS grocery_visits
     , COALESCE(f.fishmarket_visits, 0) AS fishmarket_visits
FROM   ...


  1. Jak můžeme zobrazit tělo šifrované uložené procedury v SSMS?

  2. Použití jako v MySQL pro vyhledávací operace pomocí vzoru

  3. Vygenerujte online proceduru PL/SQL pro import dat do tabulky Oracle

  4. Jaký je účel funkce String[] whereArgs in int (tabulka String, String whereClause, String[] whereArgs)?