Passer au contenu principal
eLearner.app
Module 3 · Leçon 4 sur 412/57 dans le cours~8 min
Leçons du module (4/4)

Filtrer les groupes : HAVING

Une fois que vous avez un résultat par groupe (cours précédent), vous avez souvent envie de ne conserver que les groupes qui satisfont à une condition : départements avec plus plus de 2 personnes, projets avec un budget moyen supérieur à 100k, utilisateurs avec au moins 10 commandes. Pour ce faire, WHERE ne suffit pas.

Pourquoi OÙ ne suffit pas

WHERE filtre les lignes du tableau, avant l'agrégation. Donc ça ne peut pas voir le résultat de COUNT(*) ou AVG(...) : au moment où WHERE s'exécute, ceux-ci les valeurs n'ont pas encore été calculées.

SQL
-- ERROR: COUNT(*) doesn't exist yet when WHERE is evaluated
SELECT department_id, COUNT(*) AS count
FROM   employees
WHERE  COUNT(*) > 2     -- ❌ doesn't work
GROUP BY department_id;

Pour filtrer après l'agrégation, il existe une clause dédiée : HAVING.

La syntaxe

SQL
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM   table
GROUP BY grouping_column
HAVING   condition_on_aggregate;
SQL
-- Departments with more than 2 employees:
SELECT department_id, COUNT(*) AS count
FROM   employees
GROUP BY department_id
HAVING   COUNT(*) > 2;

HAVING est à GROUP BY ce que WHERE est à FROM : la même idée ("filtre"), mais appliqué après le regroupement, sur l'ensemble.

L'ordre logique des clauses

Pour ne plus jamais confondre WHERE et HAVING, rappelez-vous l'ordre dans lequel SQL les exécute mentalement :

  1. FROM / JOIN — construit la table de départ en joignant les sources.
  2. WHERE — supprime les lignes qui ne vous intéressent pas.
  3. GROUP BY — collecte les lignes restantes en groupes.
  4. HAVING — supprime les groupes qui ne vous intéressent pas.
  5. SELECT — calcule les colonnes finales (y compris les agrégats).
  6. ORDER BY / LIMIT — réorganiser et couper.

Remarques importantes :

  • dans WHERE vous ne pouvez utiliser que des colonnes de tableau ;
  • dans HAVING, vous pouvez utiliser le regroupement de colonnes et d'agrégats.
SQL
-- Classic combo: filter first, group, filter the groups, sort.
SELECT d.name, AVG(e.salary) AS average
FROM   employees   AS e
JOIN   departments AS d ON e.department_id = d.id
WHERE  e.hired_on >= '2018-01-01'   -- filter rows
GROUP BY d.name
HAVING   AVG(e.salary) > 35000      -- filter groups
ORDER BY average DESC;

Essayez-le

Exercice#sql.m3.l4.e1
Tentatives : 0Chargement…

Pour chaque département, affichez le nom (departments.name) et le nombre d'employés, MAIS uniquement pour les départements comptant au moins 2 employés. Deux colonnes, une ligne par département éligible.

Chargement de l'éditeur…
Afficher l'indice

La condition 'au moins 2' devient COUNT(*) >= 2 dans HAVING.

Solution disponible après 3 tentatives

Exercice de révision

Exercice#sql.m3.l4.e2
Tentatives : 0Chargement…

Affichez les départements (departments.name) dont le salaire moyen dépasse 35 000. Ne considérez que les employés embauchés à partir de 2018. Deux colonnes : le nom et la moyenne. Trier par moyenne décroissante.

Chargement de l'éditeur…
Afficher l'indice

WHERE filtre les lignes (employés embauchés à partir de 2018), HAVING filtre les groupes (moyenne > 35000).

Solution disponible après 3 tentatives