📊 Module 4 – Agrégations simples & avancées (GROUP BY
, HAVING
, FILTER
, GROUPING SETS
)#
🎯 Objectifs du module#
À la fin de ce module, tu sauras :
- Utiliser les agrégations classiques (
SUM
,AVG
,COUNT
, etc.) - Différencier
WHERE
vsHAVING
- Filtrer une agrégation avec
FILTER
- Grouper de plusieurs manières avec
GROUPING SETS
,ROLLUP
,CUBE
📌 1. Agrégations classiques#
SELECT
client_id,
COUNT(*) AS nb_commandes,
SUM(montant) AS total
FROM commandes
GROUP BY client_id;
⚠️ 2. WHERE vs HAVING#
Clause | Sert à… | S’utilise quand ? |
---|---|---|
WHERE | Filtrer les lignes avant l’agrégation | Sur des colonnes |
HAVING | Filtrer les groupes après l’agrégation | Sur des agrégats |
✅ Exemple#
-- Clients avec au moins 5 commandes
SELECT client_id, COUNT(*) AS nb
FROM commandes
GROUP BY client_id
HAVING COUNT(*) >= 5;
🧼 3. FILTER – appliquer une agrégation conditionnelle#
💡 Très pratique pour éviter les CASE WHEN
dans les SUM
/COUNT
.
✅ Exemple 1 – Total et total des commandes > 100#
SELECT
client_id,
COUNT(*) AS nb_total,
COUNT(*) FILTER (WHERE montant > 100) AS nb_grandes_commandes
FROM commandes
GROUP BY client_id;
= Plus lisible que :
COUNT(CASE WHEN montant > 100 THEN 1 ELSE NULL END)
🧮 4. GROUPING SETS / ROLLUP / CUBE#
Permet de faire plusieurs agrégations d’un coup (comme un UNION
automatique).
🔹 GROUPING SETS#
SELECT region, produit, SUM(montant)
FROM ventes
GROUP BY GROUPING SETS (
(region, produit),
(region),
(produit),
()
);
👉 Ça fait 4 agrégations :
- par région & produit
- par région
- par produit
- total général
🔹 ROLLUP#
Cas particulier de GROUPING SETS
, pour hiérarchie top-down.
SELECT region, produit, SUM(montant)
FROM ventes
GROUP BY ROLLUP(region, produit);
→ Donne :
- région + produit
- région seule
- total général
🔹 CUBE#
Combine toutes les combinaisons possibles des colonnes groupées.
SELECT region, produit, SUM(montant)
FROM ventes
GROUP BY CUBE(region, produit);
→ Donne :
- region + produit
- region seule
- produit seul
- total général
🧯 5. Pièges à éviter#
⚠️ Piège | ✅ Solution |
---|---|
HAVING au lieu de WHERE (ou inversement) | Réserve HAVING aux valeurs calculées |
Ambiguïtés avec ROLLUP , GROUPING SETS | Utilise GROUPING() pour savoir si une ligne est un total |
Agrégation sur des NULLs inattendus | Utilise COALESCE pour te protéger |
🏋️♂️ 6. Exercices#
Exo 1 – Pour chaque client, afficher :#
- nombre de commandes
- total des montants
- nombre de commandes > 100
Exo 2 – N’afficher que les clients avec au moins 2 commandes > 200#
Exo 3 – Regrouper les ventes par produit
et region
, avec un total général#
Exo 4 – Afficher tous les regroupements possibles (produit, region, global) avec CUBE
#
🧰 7. Test rapide dans DuckDB (Python)#
duckdb.sql("""
SELECT
client_id,
COUNT(*) AS total,
COUNT(*) FILTER (WHERE montant > 100) AS nb_grandes
FROM commandes
GROUP BY client_id
HAVING COUNT(*) >= 2;
""").df()