Kodokon kodokon.com

HAVING et agrégations avancées

Filtrez après agrégation avec HAVING et pivotez vos données avec CASE WHEN dans les fonctions d'agrégat.

8 min · 3 questions

Ouvrir cette leçon dans Kodokon

Vous maîtrisez déjà GROUP BY. Ce module attaque ce qui distingue une requête correcte d'une requête professionnelle : filtrage post-agrégation, agrégats conditionnels, et la connaissance fine de l'ordre d'évaluation. Pour pratiquer, ouvrez sqliteonline.com (moteur SQLite) ou lancez sqlite3 dans un terminal : chaque leçon fournit les CREATE TABLE et INSERT nécessaires. Copiez ce jeu de données avant d'exécuter les exemples.

SQL
CREATE TABLE orders (
  id INTEGER PRIMARY KEY,
  customer TEXT NOT NULL,
  category TEXT NOT NULL,
  amount REAL NOT NULL,
  status TEXT NOT NULL
);

INSERT INTO orders (customer, category, amount, status)
VALUES
  ('alice', 'books', 42.0, 'paid'),
  ('alice', 'games', 55.0, 'paid'),
  ('alice', 'books', 18.5, 'refunded'),
  ('bruno', 'games', 70.0, 'paid'),
  ('bruno', 'books', 12.0, 'paid'),
  ('chloe', 'games', 95.0, 'paid'),
  ('chloe', 'books', 30.0, 'paid'),
  ('david', 'books', 8.0, 'refunded');
Jeu de données de la leçon, à exécuter en premier.

L'ordre logique d'évaluation est la clé : FROMWHEREGROUP BYHAVINGSELECTORDER BY. WHERE filtre des lignes avant le regroupement ; HAVING filtre des groupes après le calcul des agrégats. C'est pourquoi WHERE SUM(amount) > 90 est illégal : au moment du WHERE, aucune somme n'existe encore. Ici, on ne garde que les clients dont le total payé dépasse 90 (attendu : alice et chloe).

SQL
SELECT customer,
       COUNT(*) AS nb_orders,
       SUM(amount) AS total
FROM orders
WHERE status = 'paid'
GROUP BY customer
HAVING SUM(amount) > 90;
WHERE élimine les lignes, HAVING élimine les groupes.

Deuxième pattern indispensable : l'agrégat conditionnel. En glissant un CASE WHEN dans SUM ou COUNT, vous calculez plusieurs indicateurs en une seule passe sur la table, là où un débutant enchaînerait trois requêtes. C'est la technique standard pour pivoter des lignes en colonnes.

SQL
SELECT customer,
  SUM(CASE WHEN category = 'books'
      THEN amount ELSE 0 END) AS books_total,
  SUM(CASE WHEN category = 'games'
      THEN amount ELSE 0 END) AS games_total
FROM orders
WHERE status = 'paid'
GROUP BY customer;
Pivot lignes → colonnes en une seule lecture.

Quiz de validation

Vérifiez que vous avez bien retenu les points clés de cette leçon.

  1. Dans quel ordre logique le moteur évalue-t-il ces clauses ?
    • WHERE → GROUP BY → HAVING
    • HAVING → WHERE → GROUP BY
    • GROUP BY → HAVING → WHERE
  2. Quelle condition doit rester dans WHERE plutôt que dans HAVING ?
    • SUM(amount) > 100
    • status = 'paid'
    • COUNT(*) >= 2
  3. Que calcule SUM(CASE WHEN category = 'books' THEN amount ELSE 0 END) ?
    • Le total de toutes les commandes
    • Le total des seules lignes de catégorie 'books'
    • Le nombre de lignes de catégorie 'books'
    • Le total des lignes hors 'books'