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
JOINsyntax. Gör det så mycket lättare att läsa och förstå (och felsöka). -
Genom att gå med i flera
1:nrelaterade tabeller, skulle rader multiplicera varandra och producera en kartesisk produkt – vilket är väldigt dyrt nonsens. Det är en oavsiktligCROSS JOINgenom ombud. Relaterat: -
För att undvika detta, gå med som mest ett
n-tabell till1-tabell innan du aggregerar (GROUP BY). Du kan aggregera två gånger, men det är renare och snabbare att aggregeran-tabeller separat före koppla dem till1-tabell. -
I motsats till ditt original (med implicit
INNER JOIN). Jag använderLEFT JOINför att undvika att tappa rader frånfoosom inte har någon matchande rad ifoo_barellertag. -
När den oavsiktliga
CROSS JOINtas bort från frågan, finns det inget behov av att lägga tillDISTINCTlängre - förutsatt attfoo.idär unik.