sql >> Databasteknik >  >> RDS >> PostgreSQL

Två SQL LEFT JOINS ger felaktigt resultat

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   ...


  1. Hur kan jag ta bort dubbletter av rader?

  2. Bästa tillvägagångssätt för grupperad median

  3. Oracle CLOB kan inte infoga mer än 4000 tecken?

  4. Extrahera månaden från ett datum i PostgreSQL