On va refaire un tour sur l'ordre d'exécution des opérations en SQL, et aussi sur ce que WHERE et HAVING peuvent ou ne peuvent pas faire. C'est super important, parce que plein de subtilités des requêtes SQL reposent là-dessus. Il faut vraiment piger ce truc.
Alors, c'est quoi la différence entre WHERE et HAVING, quand utiliser l'un ou l'autre, et comment ils sont liés ? Ça va t'aider à pas te perdre dans la logique des requêtes et à filtrer tes données efficacement. Résumons un peu ce qu'on sait sur WHERE et HAVING.
C'est quoi WHERE ?
WHERE — c'est une condition qui sert à filtrer les lignes avant le groupement ou l'utilisation des fonctions d'agrégation. Donc, d'abord on sélectionne les lignes qui matchent les critères, et ensuite seulement on fait le groupement sur ce qui reste.
👉 Imagine que tu fais le marché pour acheter des fruits. WHERE — c'est le filtre qui te permet de virer les pommes pourries avant même de commencer à les trier par taille ou couleur.
Exemple :
SELECT *
FROM students
WHERE age > 18;
Cette requête va sélectionner tous les étudiants de plus de 18 ans avant toute autre opération.
C'est quoi HAVING ?
HAVING — c'est un filtre qui s'applique après le groupement des données (GROUP BY). Il permet de poser des conditions sur les groupes, genre ne garder que ceux où la moyenne des notes est supérieure à 80.
👉 Toujours avec les pommes : HAVING — c'est le filtre que tu utilises après avoir trié les pommes dans des paniers (groupes). Maintenant, tu veux par exemple ne garder que les paniers (groupes) où il y a plus de dix pommes.
Exemple :
SELECT panier, COUNT(*)
FROM pommes
GROUP BY panier
HAVING COUNT(*) > 10;
Cette requête va sélectionner seulement les paniers où il y a plus de 10 pommes.
Différences principales :
| Caractéristique | WHERE |
HAVING |
|---|---|---|
| Application | Filtre les lignes avant le groupement | Filtre les groupes après le groupement |
| Fonctions d'agrégation | Impossible d'utiliser des fonctions d'agrégation | On peut utiliser des fonctions d'agrégation |
| But | Vire les lignes inutiles pour le groupement | Vire les groupes qui ne remplissent pas la condition |
Ordre d'exécution de WHERE, GROUP BY et HAVING
Pour mieux piger comment marchent WHERE et HAVING, regarde l'ordre d'exécution d'une requête SQL :
- D'abord,
FROM: on sélectionne les lignes de la table. - Puis
WHERE: on ne garde que les lignes qui matchent la condition. - Ensuite, on fait le groupement avec
GROUP BY. On obtient une nouvelle table avec les groupes. - On applique
HAVING: on ne garde que les groupes qui matchent la condition. - Enfin, on sélectionne les résultats avec
SELECT.
Schématiquement, ça donne :
1. FROM → 2. WHERE → 3. GROUP BY → 4. HAVING → 5. SELECT
Exemple :
SELECT department, AVG(age) AS avg_age
FROM students
WHERE age > 18
GROUP BY department
HAVING AVG(age) > 20;
Voilà ce qui se passe ici :
- Dans la table
students, on sélectionne les lignes oùage > 18(WHERE). - Les lignes restantes sont groupées par
department. - Pour chaque groupe, on calcule l'âge moyen des étudiants.
- Les groupes où la moyenne est inférieure ou égale à 20 sont exclus (
HAVING). - On affiche les résultats.
Exemples d'utilisation combinée
Exemple 1 : Filtrage avant et après le groupement
But : trouver les départements où il y a plus de 5 étudiants, en ne prenant en compte que les étudiants de plus de 18 ans.
Table de départ students
| id | name | department | age | gpa |
|---|---|---|---|---|
| 1 | Alex Lin | ComputerSci | 20 | 3.8 |
| 2 | Maria Chi | Math | 22 | 3.5 |
| 3 | Anna Song | ComputerSci | 19 | 4.0 |
| 4 | Otto Art | Math | 17 | 3.9 |
| 5 | Liam Park | Physics | 21 | 3.7 |
| 6 | Jane Doe | ComputerSci | 23 | 3.6 |
| 7 | Tom Brown | Math | 25 | 3.4 |
| 8 | Sara White | Math | 19 | 3.8 |
| 9 | John Smith | ComputerSci | 20 | 3.7 |
| 10 | Emily Green | Physics | 18 | 3.9 |
| 11 | Mark Blue | ComputerSci | 21 | 3.5 |
| 12 | Zoe Black | Math | 22 | 3.6 |
| 13 | Max Gray | ComputerSci | 20 | 3.9 |
| 14 | Eva Gold | Math | 23 | 3.7 |
| 15 | Nick Silver | Physics | 19 | 3.8 |
Requête :
SELECT department, COUNT(*) AS student_count
FROM students
WHERE age > 18
GROUP BY department
HAVING COUNT(*) > 5;
Résultat : -- Résultat de la requête
| department | student_count |
|---|---|
| ComputerSci | 6 |
Explication :
- D'abord, on enlève les lignes où
age <= 18(conditionWHERE). - On groupe les données par département (
GROUP BY department). - On compte le nombre d'étudiants dans chaque groupe.
- On vire les groupes où il y a 5 étudiants ou moins (
HAVING COUNT(*) > 5).
Exemple 2 : Erreur en utilisant WHERE au lieu de HAVING
But : Trouver les départements où l'âge moyen est supérieur à 22 ans.
Requête incorrecte :
SELECT department, AVG(age) AS avg_age
FROM students
WHERE AVG(age) > 22
GROUP BY department;
Erreur : SQL ne permet pas d'utiliser des fonctions d'agrégation AVG dans WHERE, car à ce stade les agrégats ne sont pas encore calculés.
Bonne requête :
SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 22;
Ici, la condition AVG(age) > 22 s'applique après le groupement.
Conseils pratiques
Si tu veux filtrer des lignes, utilise WHERE. Exemple : Trouver tous les employés avec un salaire supérieur à 5000.
SELECT *
FROM employees
WHERE salary > 5000;
Si tu veux filtrer des groupes, utilise HAVING. Exemple : Trouver les départements avec un salaire total supérieur à 100 000.
SELECT department, SUM(salary) AS total_salary
FROM employees
GROUP BY department
HAVING SUM(salary) > 100000;
Combine WHERE et HAVING pour des conditions plus complexes.
Exemple : Trouver les pays avec plus de 10 millions d'habitants, en ne prenant en compte que les villes de plus d'un million d'habitants.
SELECT country, SUM(population) AS total_population
FROM cities
WHERE population > 1000000
GROUP BY country
HAVING SUM(population) > 10000000;
Erreurs courantes et comment les éviter
Une des erreurs les plus fréquentes — c'est de confondre WHERE et HAVING. Par exemple, essayer d'utiliser une fonction d'agrégation dans WHERE :
SELECT department, COUNT(*)
FROM students
WHERE COUNT(*) > 10
GROUP BY department;
Cette requête va planter, parce que les calculs d'agrégats ne sont pas dispos à l'étape WHERE. La bonne façon — c'est d'utiliser HAVING :
SELECT department, COUNT(*)
FROM students
GROUP BY department
HAVING COUNT(*) > 10;
Une autre erreur, c'est de mettre la mauvaise condition dans WHERE. Par exemple :
SELECT department, AVG(age) AS avg_age
FROM students
WHERE avg_age > 20
GROUP BY department;
Ici, la condition avg_age > 20 ne marche pas, parce que avg_age n'est pas encore calculé. Solution — déplace cette condition dans HAVING :
SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 20;
J'espère que maintenant tu piges bien la différence entre WHERE et HAVING, comment les utiliser correctement et comment éviter les erreurs classiques. Ces connaissances te serviront pour faire des rapports complexes, filtrer des données pour l'analyse et optimiser tes requêtes. Bref, pour la majorité des requêtes SQL que tu vas écrire :)
GO TO FULL VERSION