Niveau 8 : Filtrer les groupes avec HAVING

Niveau 8 : Filtrer les groupes avec HAVING

Mis à jour le

Intermédiaire · niveau 8 sur 20. Objectif : Ne garder que les groupes qui respectent une condition sur un agrégat.

Notions : HAVING WHERE ou HAVING

Leçon

Une fois les paquets formés par GROUP BY, on veut parfois n'en garder que certains : les vendeurs dont le total dépasse 1200, les services de plus de 2 personnes. Ce filtre porte sur un agrégat, qui n'existe qu'après le regroupement.

WHERE ne peut pas le faire : il agit avant le regroupement, ligne par ligne, quand les totaux ne sont pas encore calculés. WHERE SUM(amount) > 1200 provoque donc une erreur. HAVING est le WHERE des groupes : il s'exécute après GROUP BY et teste les agrégats.

HAVING se place juste après GROUP BY : GROUP BY seller HAVING SUM(amount) > 1200. Sur les ventes, Ana (1150) et Dan (900) sont écartés, Ben (1450) et Cleo (1550) restent. L'agrégat testé n'a pas besoin d'être affiché dans le SELECT.

WHERE et HAVING se combinent : WHERE choisit les lignes qui entrent dans le calcul, HAVING choisit les groupes qui sortent. Avec WHERE region = 'North' … GROUP BY seller HAVING SUM(amount) > 1200, les totaux ne sont calculés que sur les ventes du Nord, puis seuls les gros totaux sont gardés.

Règle pratique : une condition sur une colonne ordinaire va dans WHERE, une condition sur un agrégat va dans HAVING.

Ordre d'exécution complet : FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT. Garde-le en tête : il explique où chaque filtre a le droit d'aller.

Syntaxe

SELECT colonne, AGG(x)
FROM ma_table
WHERE …
GROUP BY colonne
HAVING AGG(x) > valeur;

Exemple commenté

SELECT seller, SUM(amount) AS total
FROM sales
GROUP BY seller
HAVING SUM(amount) > 1200;

On calcule le total de chaque vendeur, puis on ne garde que ceux qui dépassent 1200.

Table sales (12 lignes)
idsellerregionmonthamount
1AnaNorth2025-01300
2AnaNorth2025-02450
3AnaNorth2025-03400
4BenNorth2025-01500
5BenNorth2025-02350
6BenNorth2025-03600
7CleoSouth2025-01200
8CleoSouth2025-02700
9CleoSouth2025-03650
10DanSouth2025-01400
11DanSouth2025-02400
12DanSouth2025-03100

Résultat de l’exemple

sellertotal
Ben1450
Cleo1550

À retenir

  • WHERE : condition sur les lignes. HAVING : condition sur les groupes.
  • HAVING vient après GROUP BY.
  • Un agrégat dans une condition doit être dans HAVING.

Pièges fréquents

  • WHERE COUNT(*) > 2 provoque une erreur : c'est HAVING COUNT(*) > 2.
  • Une condition sur une colonne non regroupée (GROUP BY seller HAVING month = '2025-01') est une erreur en SQL standard. SQLite l'accepte mais ne teste qu'une ligne quelconque du groupe : place-la dans WHERE. Sur une colonne du GROUP BY, elle est permise dans HAVING, mais plus claire et plus rapide dans WHERE.

Les 5 exercices du niveau

  1. Guidé · Affiche les services qui comptent plus de 2 employés, avec leur nombre d'employés. (Table : staff)
  2. Entraînement · Affiche les matières dont la moyenne des notes est d'au moins 12.5, avec cette moyenne. (Table : grades)
  3. Entraînement · Affiche l'identifiant des membres qui ont fait au moins 3 prêts, avec leur nombre de prêts. (Table : loans)
  4. Entraînement · En ne comptant que les vols de moins de 120 minutes, affiche les compagnies qui ont vendu plus de 300 places, avec leur total. (Table : flights)
  5. Défi · Affiche les artistes (artist_id) dont la durée moyenne des chansons dépasse 240 secondes, avec cette moyenne, de la plus longue à la plus courte. (Table : songs)

Dans SpeedQL, chaque requête est corrigée tout de suite : le résultat est comparé à celui attendu, puis la requête est relancée sur une base de contrôle cachée. Chaque exercice a ses indices écrits, à afficher seulement si tu bloques.

Voir aussi : la fiche de l’aide-mémoire · les exercices SQL corrigés sur cette notion

Faire les exercices du niveau 8

Gratuit, sans inscription : la leçon et les 5 exercices s’ouvrent directement dans ton navigateur.

Ouvrir le niveau 8 dans SpeedQL

·