PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Aggregieren Sie Funktionen in mehreren verknüpften Tabellen

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 unbeabsichtigten CROSS JOIN per Stellvertreter. Verwandte:

  • Um dies zu vermeiden, treten Sie höchstens einem bei n -Tabelle zum 1 -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 der 1 an -Tisch.

  • Im Gegensatz zu Ihrem Original (mit implizitem INNER JOIN ). Ich verwende LEFT JOIN um zu vermeiden, Zeilen von foo zu verlieren die keine übereinstimmende Zeile in foo_bar haben oder tag .

  • Einmal das unbeabsichtigte CROSS JOIN aus der Abfrage entfernt wird, muss DISTINCT nicht hinzugefügt werden nicht mehr - vorausgesetzt, dass foo.id ist einzigartig.