sql >> Database >  >> RDS >> PostgreSQL

Geaggregeerde functies op meerdere samengevoegde 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;

Produceert het gewenste resultaat.

  • Herschrijven met expliciete JOIN syntaxis. Maakt het zoveel gemakkelijker te lezen en te begrijpen (en debuggen).

  • Door lid te worden van meerdere 1:n gerelateerde tabellen, zouden rijen elkaar vermenigvuldigen en een Cartesiaans product produceren - wat erg dure onzin is. Het is een onbedoelde CROSS JOIN bij volmacht. Gerelateerd:

  • Om dit te voorkomen, moet u maximaal één deelnemen n -tabel naar de 1 -tabel voordat u aggregeert (GROUP BY ). Je zou twee keer kunnen aggregeren, maar het is schoner en sneller om n te aggregeren -tabellen afzonderlijk voor voeg ze toe aan de 1 -tafel.

  • In tegenstelling tot uw originele (met impliciete INNER JOIN ). Ik gebruik LEFT JOIN om te voorkomen dat u rijen verliest van foo die geen overeenkomende rij hebben in foo_bar of tag .

  • Zodra de onbedoelde CROSS JOIN is verwijderd uit de zoekopdracht, is het niet nodig om DISTINCT toe te voegen meer - ervan uitgaande dat foo.id is uniek.




  1. RTRIM of REGEXP_REPLACE gebruiken om een ​​komma te vervangen door een kommaruimte en een enkel aanhalingsteken

  2. Verbind Django met een externe mysql-server op een lokaal netwerk

  3. Wat is het verschil tussen de functies RANK() en DENSE_RANK() in Oracle?

  4. MySQL INSERT SELECT - Dubbele rijen