Maison >base de données >tutoriel mysql >Comment éviter les données redondantes lors de la combinaison de plusieurs appels `array_agg()` dans une seule requête SQL ?

Comment éviter les données redondantes lors de la combinaison de plusieurs appels `array_agg()` dans une seule requête SQL ?

Linda Hamilton
Linda Hamiltonoriginal
2024-12-29 13:56:23696parcourir

How to Avoid Redundant Data When Combining Multiple `array_agg()` Calls in a Single SQL Query?

Combinaison de plusieurs appels array_agg() dans une seule requête

Dans votre requête, vous rencontrez un problème où plusieurs appels array_agg() renvoient des éléments redondants données. La présence de lignes en double en raison de plusieurs jointures entraîne des résultats indésirables. Pour résoudre ce problème, nous pouvons explorer plusieurs approches qui évitent la multiplication des lignes dès le départ.

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

Une méthode efficace consiste à agréger les données dans les sous-requêtes avant d’effectuer les jointures. Cela garantit que chaque enregistrement d'employé est unique, empêchant ainsi la multiplication des lignes. La requête modifiée ressemblerait à ceci :

SELECT e.id, 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 / JOIN LATERAL

Une autre approche consiste à utiliser des sous-requêtes corrélées ou JOIN LATERAL dans PostgreSQL 9.3 ou plus tard. Cette technique permet de récupérer les données agrégées pour chaque collaborateur au sein de la requête principale. Les requêtes modifiées seraient :

Sous-requêtes corrélé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

JOIN LATERAL :

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

Conclusion

En mettant en œuvre ces approches, vous pouvez éviter la multiplication des lignes et obtenir le résultat souhaité, qui est un tableau d'adresses et un tableau de jours de travail pour chaque employé. Ces solutions garantissent que les données sont agrégées de manière appropriée et fusionnées correctement, éliminant ainsi le besoin de filtrage ou de post-traitement supplémentaire.

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