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;
Daje pożądany rezultat.
-
Przepisz z jawnym
JOIN
składnia. Znacznie ułatwia czytanie i zrozumienie (i debugowanie). -
Łącząc się z wieloma
1:n
powiązanych tabel, wiersze mnożą się nawzajem, tworząc produkt kartezjański - co jest bardzo kosztownym nonsensem. To niezamierzoneCROSS JOIN
przez pełnomocnika. Powiązane: -
Aby tego uniknąć, dołącz co najwyżej do jednego
n
-table do1
-table przed agregacją (GROUP BY
). Możesz agregować dwa razy, ale agregacjan
jest czystsza i szybsza -tabele oddzielnie przed dołączanie ich do1
-stół. -
W przeciwieństwie do oryginału (z niejawnym
INNER JOIN
). UżywamLEFT JOIN
aby uniknąć utraty wierszy zfoo
które nie mają pasującego wiersza wfoo_bar
lubtag
. -
Po niezamierzonym
CROSS JOIN
zostanie usunięty z zapytania, nie ma potrzeby dodawaniaDISTINCT
więcej - zakładając, żefoo.id
jest wyjątkowy.