PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Funzioni aggregate su più tabelle unite

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;

Produce il risultato desiderato.

  • Riscrivi con JOIN esplicito sintassi. Semplifica molto la lettura e la comprensione (e il debug).

  • Unendo a più 1:n tabelle correlate, le righe si moltiplicherebbero a vicenda producendo un prodotto cartesiano - che è una sciocchezza molto costosa. È un CROSS JOIN non intenzionale per delega. Correlati:

  • Per evitare ciò, unisciti al massimo a uno n -tabella al 1 -table prima di aggregare (GROUP BY ). Puoi aggregare due volte, ma è più semplice e veloce aggregare n -tabelle separatamente prima unendoli al 1 -tavolo.

  • Al contrario del tuo originale (con INNER JOIN implicito ). Uso LEFT JOIN per evitare di perdere righe da foo che non hanno una riga corrispondente in foo_bar o tag .

  • Dopo l'indesiderato CROSS JOIN viene rimosso dalla query, non è necessario aggiungere DISTINCT più - supponendo che foo.id è unico.