GROUP BY, HAVING et fonctions d'agrégation : le guide complet
Les fonctions d'agrégation permettent de résumer plusieurs lignes en une seule valeur : total, moyenne, nombre d'éléments, etc. Combinées à GROUP BY, elles deviennent l'un des outils les plus puissants du SQL.
Les fonctions d'agrégation de base
| Fonction | Rôle |
|---|---|
| COUNT(*) | Compte le nombre de lignes |
| SUM(colonne) | Additionne les valeurs |
| AVG(colonne) | Calcule la moyenne |
| MIN(colonne) / MAX(colonne) | Trouve la valeur minimale / maximale |
SELECT COUNT(*) AS nb_commandes, SUM(montant) AS total
FROM commandes;
GROUP BY : regrouper avant d'agréger
GROUP BY regroupe les lignes ayant la même valeur dans une ou plusieurs colonnes, puis applique la fonction d'agrégation à chaque groupe séparément.
SELECT client_id, COUNT(*) AS nb_commandes, SUM(montant) AS total
FROM commandes
GROUP BY client_id;
Règle importante : toute colonne présente dans le SELECT qui n'est pas dans une fonction d'agrégation doit apparaître dans le GROUP BY.
HAVING : filtrer après l'agrégation
WHERE filtre les lignes avant le regroupement ; HAVING filtre les groupes après le calcul de l'agrégation. C'est la confusion la plus fréquente chez les débutants.
SELECT client_id, SUM(montant) AS total
FROM commandes
WHERE montant > 0
GROUP BY client_id
HAVING SUM(montant) > 200;
WHERE SUM(montant) > 200 — au moment où WHERE s'exécute, l'agrégation n'a pas encore eu lieu. Utilisez toujours HAVING pour filtrer sur un résultat agrégé.L'ordre réel d'exécution d'une requête SQL
Contrairement à l'ordre dans lequel on écrit une requête, le moteur SQL l'exécute dans cet ordre logique :
FROM— identifier les tablesWHERE— filtrer les lignes individuellesGROUP BY— regrouper les lignes restantesHAVING— filtrer les groupesSELECT— choisir les colonnes et calculer les agrégationsORDER BY— trier le résultat finalLIMIT— limiter le nombre de lignes renvoyées
Comprendre cet ordre explique pourquoi on ne peut pas utiliser un alias du SELECT dans le WHERE, mais qu'on peut souvent l'utiliser dans ORDER BY.
Exemple complet
SELECT
c.nom,
COUNT(co.id) AS nb_commandes,
SUM(co.montant) AS total_depense
FROM clients c
LEFT JOIN commandes co ON co.client_id = c.id
GROUP BY c.nom
HAVING COUNT(co.id) >= 1
ORDER BY total_depense DESC
LIMIT 10;
Cette requête retourne les 10 clients ayant dépensé le plus, classés par montant décroissant, en excluant ceux sans aucune commande.
