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
JOIN
Syntax. Macht es so viel einfacher zu lesen und zu verstehen (und zu debuggen). -
Durch Zusammenschluss mit mehreren
1:n
verwandte Tabellen, Zeilen würden sich gegenseitig multiplizieren und ein kartesisches Produkt erzeugen - das ist sehr teurer Unsinn. Es handelt sich um einen unbeabsichtigtenCROSS JOIN
per 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,n
zu aggregieren -Tabellen separat vor schließe sie der1
an -Tisch. -
Im Gegensatz zu Ihrem Original (mit implizitem
INNER JOIN
). Ich verwendeLEFT JOIN
um zu vermeiden, Zeilen vonfoo
zu verlieren die keine übereinstimmende Zeile infoo_bar
haben odertag
. -
Einmal das unbeabsichtigte
CROSS JOIN
aus der Abfrage entfernt wird, mussDISTINCT
nicht hinzugefügt werden nicht mehr - vorausgesetzt, dassfoo.id
ist einzigartig.