PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Fonctions d'agrégation sur plusieurs tables jointes

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;

Produit le résultat souhaité.

  • Réécrire avec un JOIN explicite syntaxe. Facilite grandement la lecture et la compréhension (et le débogage).

  • En se joignant à plusieurs 1:n tables liées, les lignes se multiplieraient produisant un produit cartésien - ce qui est un non-sens très coûteux. C'est un CROSS JOIN involontaire par procuration. Connexe :

  • Pour éviter cela, rejoignez au plus un n -table au 1 -table avant d'agréger (GROUP BY ). Vous pouvez agréger deux fois, mais c'est plus propre et plus rapide d'agréger n -tables séparément avant les joindre au 1 -table.

  • Contrairement à votre original (avec INNER JOIN implicite ). J'utilise LEFT JOIN pour éviter de perdre des lignes de foo qui n'ont pas de ligne correspondante dans foo_bar ou tag .

  • Une fois le CROSS JOIN involontaire est supprimé de la requête, il n'est pas nécessaire d'ajouter DISTINCT plus - en supposant que foo.id est unique.