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;
Giver det ønskede resultat.
-
Omskriv med eksplicit
JOIN
syntaks. Gør det så meget nemmere at læse og forstå (og fejlfinde). -
Ved at slutte sig til flere
1:n
relaterede tabeller, ville rækker multiplicere hinanden og producere et kartesisk produkt - hvilket er meget dyrt sludder. Det er en utilsigtetCROSS JOIN
ved fuldmagt. Relateret: -
For at undgå dette, tilmeld dig højst én
n
-tabellen til1
-tabel, før du samler (GROUP BY
). Du kan samle to gange, men det er renere og hurtigere at samlen
-tabeller separat før forbinder dem med1
-bord. -
I modsætning til din originale (med implicit
INNER JOIN
). Jeg brugerLEFT JOIN
for at undgå at miste rækker frafoo
der ikke har nogen matchende række ifoo_bar
ellertag
. -
Når den utilsigtede
CROSS JOIN
er fjernet fra forespørgslen, er der ikke behov for at tilføjeDISTINCT
mere - forudsat atfoo.id
er unik.