Un truc qu’on n’a pas encore vu, c’est comment filtrer les groupes après avoir appliqué des agrégats ? Parfois, on ne veut pas tous les départements — juste ceux où il y a plus de cent étudiants. Ou alors on veut voir uniquement les services où le salaire moyen dépasse 50 000. Aujourd’hui, on va découvrir comment filtrer les données agrégées avec HAVING.
Mais pourquoi on a besoin de HAVING alors qu’on a déjà WHERE ? On pourrait juste mettre WHERE après GROUP BY :)
C’est pas si simple ! Déjà, l’ordre des opérateurs en SQL est fixé et WHERE s’exécute avant GROUP BY.
Et si on essayait de le mettre après GROUP BY ?
Non plus ! Très souvent, il faut filtrer les lignes du tableau avant de grouper. Ensuite, on fait le groupement sur les données filtrées. Et après, on veut encore virer des groupes inutiles après l’agrégation.
Alors, on pourrait juste copier l’opérateur WHERE, l’appeler HAVING et le coller après GROUP BY ?
Ouais, c’est exactement ça ! :)
Différence entre HAVING et WHERE
WHERE filtre les lignes avant le groupement.
Imagine que tu sélectionnes des gâteaux selon leur goût : tu gardes les fraise et chocolat, les autres tu les mets de côté. Ça, c’est le taf de WHERE.
HAVING filtre après que les données ont été groupées et que les fonctions d’agrégat ont fait leur magie.
Par exemple, t’as déjà groupé les gâteaux par table, compté combien il y en a, et maintenant tu veux garder que les tables où il y a plus de trois gâteaux.
Donc, HAVING sert à filtrer les données au niveau des groupes.
Syntaxe de HAVING
La syntaxe est presque la même que pour WHERE, mais ça marche un peu différemment :
SELECT colonnes, fonctions_aggrégées
FROM table
GROUP BY colonnes
HAVING condition;
Étapes d’exécution :
- D’abord, les lignes sont filtrées avec
WHERE. - Ensuite, les données sont groupées avec
GROUP BY. - Les fonctions d’agrégat sont appliquées aux résultats du groupement.
- Enfin, le résultat obtenu est filtré avec
HAVING.
Exemples d’utilisation de HAVING
Exemple 1 : Filtrer les facultés avec beaucoup d’étudiants
Tu veux savoir quelles facultés à l’université ont plus de 100 étudiants. Imaginons qu’on a une table students :
| id | name | faculty |
|---|---|---|
| 1 | Alice | Engineering |
| 2 | Bob | Engineering |
| 3 | Charlie | Arts |
| 4 | Daisy | Business |
| 5 | ... | ... |
Requête :
SELECT faculty, COUNT(*) AS student_count
FROM students
GROUP BY faculty
HAVING COUNT(*) > 100;
Ce qui se passe ici :
- D’abord, on groupe les étudiants par colonne
facultyavecGROUP BY. - Puis la fonction d’agrégat
COUNT(*)compte le nombre d’étudiants dans chaque faculté. - Enfin,
HAVINGvire toutes les facultés où il y a 100 étudiants ou moins.
Résultat :
| faculty | student_count |
|---|---|
| Engineering | 150 |
| Arts | 120 |
Exemple 2 : Départements avec un salaire moyen élevé
Tu veux trouver seulement les départements où le salaire moyen des employés dépasse 50 000. Imaginons qu’on a une table employees :
| id | name | department | salary |
|---|---|---|---|
| 1 | Alice | IT | 60000 |
| 2 | Bob | HR | 45000 |
| 3 | Charlie | IT | 70000 |
| 4 | Daisy | HR | 52000 |
| 5 | ... | ... | ... |
Requête :
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;
Résultat :
| department | avg_salary |
|---|---|
| IT | 65000 |
À noter : HAVING bosse avec les résultats calculés après GROUP BY.
Ordre d’exécution de WHERE, GROUP BY et HAVING
Le filtrage avec WHERE et HAVING se fait à des étapes différentes. Pour mieux piger la différence, voilà le process étape par étape :
WHERE: filtrage des lignes.À ce stade, toutes les lignes du tableau sont traitées. Si une ligne ne passe pas la condition
WHERE, elle ne va même pas plus loin.GROUP BY: groupement des lignes.Après le filtrage, les lignes sont regroupées selon les colonnes indiquées dans
GROUP BY.Fonctions d’agrégat :
Les fonctions d’agrégat comme
COUNT(),AVG(),SUM()etc. sont appliquées aux groupes.HAVING: filtrage des groupes.Là, on ne traite que les résultats des agrégats. Les conditions
HAVINGs’appliquent uniquement aux groupes.
Particularités de HAVING
Particularité 1 : Travailler avec les agrégats
La grosse différence entre HAVING et WHERE, c’est la gestion des fonctions d’agrégat. Par exemple :
SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;
Dans cette requête, tu peux pas utiliser AVG(salary) dans WHERE, parce que WHERE traite les lignes avant le groupement. Une requête comme :
SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;
va te donner une erreur : aggregate functions are not allowed in WHERE.
Particularité 2 : Filtrer sans groupement
Tu peux utiliser HAVING même sans GROUP BY explicite. Dans ce cas, la requête est vue comme s’il y avait un seul groupe — toutes les lignes :
SELECT AVG(salary) AS avg_salary
FROM employees
HAVING AVG(salary) > 50000;
Exemple pratique
Imaginons qu’on a un magasin et une table des ventes sales :
| id | product_id | sales_amount |
|---|---|---|
| 1 | 101 | 200.00 |
| 2 | 102 | 300.00 |
| 3 | 101 | 400.00 |
| 4 | 103 | 150.00 |
Requête : trouver les produits avec un total des ventes supérieur à 500.
SELECT product_id, SUM(sales_amount) AS total_sales
FROM sales
GROUP BY product_id
HAVING SUM(sales_amount) > 500;
Résultat :
| product_id | total_sales |
|---|---|
| 101 | 600.00 |
Erreurs classiques
Utiliser des agrégats dans WHERE :
Par exemple :
SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;
Erreur : tu peux pas utiliser des fonctions d’agrégat dans WHERE.
Erreurs avec NULL :
Si les données contiennent des NULL, le filtrage peut donner des résultats bizarres. Par exemple :
SELECT department, SUM(salary)
FROM employees
GROUP BY department
HAVING SUM(salary) > 0;
Si la colonne salary contient seulement des NULL, le résultat peut être zéro ou vide.
Bravo ! À ce stade, tu sais déjà filtrer les données agrégées comme un chef ! N’oublie pas, HAVING c’est ta clé pour l’analyse au niveau des groupes, là où un simple WHERE ne suffit plus.
GO TO FULL VERSION