GROUP BY est utilisé pour regrouper des lignes et agréger des données, mais si mal utilisé, il peut provoquer des erreurs graves ou un fonctionnement non optimisé.
Points clés :
Exemple :
SELECT customer_id, COUNT(*) as orders FROM orders WHERE order_date >= '2024-01-01' GROUP BY customer_id HAVING COUNT(*) > 10;
Peut-on dans SELECT après GROUP BY faire référence à des champs qui n'ont été spécifiés ni dans GROUP BY, ni dans la fonction d'agrégation ?
Réponse : Non, cela entraînera une erreur dans la plupart des implémentations SQL (par exemple, dans MS SQL, PostgreSQL). Certaines bases de données spécifiques peuvent retourner une valeur aléatoire et incorrecte (en particulier dans MySQL lorsque sql_mode 'ONLY_FULL_GROUP_BY' est désactivé), mais ce comportement est incorrect et n'est pas garanti par la norme. Exemple correct :
SELECT department, AVG(salary) FROM employees GROUP BY department;
Histoire
Dans un projet e-commerce, le rapport "revenu par produits" a été préparé avec la requête SELECT sku, price, SUM(qty) FROM orders GROUP BY sku. Ils n'ont pas pris en compte : prix n'était pas dans GROUP BY et était hors de la fonction d'agrégation, résultat — MySQL renvoyait le premier prix trouvé, ce qui, lors d'une promotion, a entraîné des erreurs sérieuses dans le rapport. Correction — soit ajouter le prix à GROUP BY, soit utiliser une fonction d'agrégation.
Histoire
Dans un projet BI, un rapport complexe avec plusieurs JOIN et GROUP BY s'exécutait en 80 minutes au lieu des 3 prévues. Après analyse, nous avons constaté : des index manquaient sur le champ GROUP BY et le filtrage, créant d'énormes tables temporaires pour l'agrégation. Solution — optimisation des index et réécriture de la requête avec des expressions de table.
Histoire
Le développeur a utilisé HAVING pour filtrer les valeurs selon un attribut utilisateur non agrégé. En conséquence, le serveur a effectué le grouping sur toutes les données, puis les a supprimées via HAVING, réduisant la performance. Correction — nous avons déplacé cette vérification dans WHERE pour réduire l'échantillon avant l'agrégation.