Maison >base de données >tutoriel mysql >Comment éviter la multiplication de lignes lors de l'utilisation de plusieurs appels « array_agg() » dans les jointures SQL ?

Comment éviter la multiplication de lignes lors de l'utilisation de plusieurs appels « array_agg() » dans les jointures SQL ?

Patricia Arquette
Patricia Arquetteoriginal
2024-12-31 14:26:14158parcourir

How to Avoid Row Multiplication When Using Multiple `array_agg()` Calls in SQL Joins?

Résolution de plusieurs appels array_agg() dans une seule requête

Lorsque vous travaillez avec plusieurs jointures impliquant des tableaux, il est essentiel de comprendre leur impact sur les résultats. Dans ce cas, la requête d'origine tente d'extraire des tableaux pour les adresses et les jours ouvrables de chaque employé. Cependant, la multiplication inattendue des lignes en raison de plusieurs jointures entraîne une agrégation incorrecte.

Solution 1 : Agréger d'abord, rejoindre plus tard

Pour résoudre ce problème, une approche efficace consiste pour agréger les données dans des sous-requêtes avant de les joindre. En séparant l'agrégation des jointures, le problème de multiplication des lignes est évité :

SELECT e.name, e.age, ad.streets, array_agg(wd.day) AS days
FROM (
   SELECT e.id, e.name, e.age, array_agg(ad.street) AS streets
   FROM employees e 
   JOIN address ad ON ad.employeeid = e.id
   GROUP BY e.id  -- PK covers whole row
) e
JOIN workingdays wd ON wd.employeeid = e.id
GROUP BY e.id, e.name, e.age;

Solution 2 : Sous-requêtes corrélées ou JOIN LATERAL

Pour un filtrage sélectif sur les employés , des sous-requêtes corrélées peuvent être utilisées :

SELECT name, age
    , (SELECT array_agg(street) FROM address WHERE employeeid = e.id) AS streets
    , (SELECT array_agg(day) FROM workingdays WHERE employeeid = e.id) AS days
FROM employees e
WHERE e.namer = 'peter';  -- very selective

Alternativement, les jointures LATERAL peuvent être employés dans Postgres 9.3 ou version ultérieure :

SELECT e.name, e.age, a.streets, w.days
FROM employees e
LEFT JOIN LATERAL (
   SELECT array_agg(street) AS streets
   FROM address
   WHERE employeeid = e.id
   GROUP BY 1
) a ON true
LEFT JOIN LATERAL (
   SELECT array_agg(day) AS days
   FROM workingdays
   WHERE employeeid = e.id
   GROUP BY 1
) w ON true
WHERE e.name = 'peter';  -- very selective

Ces approches alternatives garantissent que tous les employés qualifiés sont conservés dans le résultat, évitant ainsi le problème précédent de multiplication de lignes.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn