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;
Erzeugt das gewünschte Ergebnis.
-
Umschreiben mit explizitem
JOINSyntax. Macht es so viel einfacher zu lesen und zu verstehen (und zu debuggen). -
Durch Zusammenschluss mit mehreren
1:nverwandte Tabellen, Zeilen würden sich gegenseitig multiplizieren und ein kartesisches Produkt erzeugen - das ist sehr teurer Unsinn. Es handelt sich um einen unbeabsichtigtenCROSS JOINper Stellvertreter. Verwandte: -
Um dies zu vermeiden, treten Sie höchstens einem bei
n-Tabelle zum1-table, bevor Sie aggregieren (GROUP BY). Sie könnten zweimal aggregieren, aber es ist sauberer und schneller,nzu aggregieren -Tabellen separat vor schließe sie der1an -Tisch. -
Im Gegensatz zu Ihrem Original (mit implizitem
INNER JOIN). Ich verwendeLEFT JOINum zu vermeiden, Zeilen vonfoozu verlieren die keine übereinstimmende Zeile infoo_barhaben odertag. -
Einmal das unbeabsichtigte
CROSS JOINaus der Abfrage entfernt wird, mussDISTINCTnicht hinzugefügt werden nicht mehr - vorausgesetzt, dassfoo.idist einzigartig.