📌 Agrégations classiques#
SELECT
client_id,
COUNT(*) AS nb_commandes,
SUM(montant) AS total,
AVG(montant) AS moyenne_total
FROM commandes
GROUP BY client_id;
⚠️ 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 |
-- Clients avec au moins 5 commandes
SELECT client_id, COUNT(*) AS nb
FROM commandes
GROUP BY client_id
HAVING COUNT(*) >= 5;
🧼 FILTER – Appliquer une agrégation conditionnelle#
💡 Très pratique pour éviter les CASE WHEN dans les SUM/COUNT.
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)
🧮 GROUPING SETS / ROLLUP / CUBE#
Permet de faire plusieurs agrégations d’un coup (comme un UNION automatique).
GROUPING SETSSELECT 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 deGROUPING 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
🧯 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 |
🏋️♂️ Entraînement#
- Pour chaque client, afficher :
- nombre de commandes
- total des montants
- nombre de commandes > 100
- N’afficher que les clients avec au moins 2 commandes > 200
- Regrouper les ventes par
produitetregion, avec un total général - Afficher tous les regroupements possibles (produit, region, global) avec
CUBE
duckdb.sql("""
SELECT
client_id,
COUNT(*) AS total,
COUNT(*) FILTER (WHERE montant > 100) AS nb_grandes_commandes
FROM commandes
GROUP BY client_id
HAVING COUNT(*) >= 2;
""").df()