sql >> Databasteknik >  >> RDS >> PostgreSQL

Aggregera funktioner på flera sammanfogade tabeller

SELECT f.id, f.name, b.fb_ct, t.tag_names
FROM   foo f
LEFT JOIN  (
    SELECT foo_id AS id, count(*) AS fb_ct
    FROM   foo_bar
    GROUP  BY 1
    ) b USING (id)
LEFT JOIN  (
    SELECT target_id AS id, array_agg(name) AS tag_names
    FROM   tag
    GROUP  BY 1
    ) t USING (id)
ORDER  BY f.id;

Ger önskat resultat.

  • Skriv om med explicit JOIN syntax. Gör det så mycket lättare att läsa och förstå (och felsöka).

  • Genom att gå med i flera 1:n relaterade tabeller, skulle rader multiplicera varandra och producera en kartesisk produkt – vilket är väldigt dyrt nonsens. Det är en oavsiktlig CROSS JOIN genom ombud. Relaterat:

  • För att undvika detta, gå med som mest ett n -tabell till 1 -tabell innan du aggregerar (GROUP BY ). Du kan aggregera två gånger, men det är renare och snabbare att aggregera n -tabeller separat före koppla dem till 1 -tabell.

  • I motsats till ditt original (med implicit INNER JOIN ). Jag använder LEFT JOIN för att undvika att tappa rader från foo som inte har någon matchande rad i foo_bar eller tag .

  • När den oavsiktliga CROSS JOIN tas bort från frågan, finns det inget behov av att lägga till DISTINCT längre - förutsatt att foo.id är unik.




  1. PLS-00386:typfel överensstämmelse hittas mellan FETCH-markören och INTO-variablerna

  2. Massinlägg av MySQL-relaterade tabeller från bash

  3. MySQL regex vid körning

  4. Hur infogar man formulärdata i MySQL-databastabellen med PHP och Ajax?