Question 1Quand tu spécifies GROUP BY name, combien de lignes a le résultat (table score / 10 noms distincts) ?
GROUP BY et HAVING — Agrégats par groupe
Apprends SQL GROUP BY et HAVING : agrégats par groupe, filtrage des groupes avec HAVING et différence avec WHERE — en t'exerçant sur des données de notes CSV, directement dans ton navigateur.
Les données utilisées dans cet article — la table score
Dans l'article précédent, tu as réduit une table entière à une seule valeur. Le `GROUP BY` de cet article (regroupement — réunir dans un même groupe les lignes qui partagent la même valeur) exécute les agrégats par groupe et renvoie une ligne d'agrégat par groupe. En plus de cela, `HAVING` te permet de filtrer les résultats d'agrégat, par exemple « uniquement les groupes dont la moyenne est supérieure ou égale à 80 ».
Le sujet est la même table score que la dernière fois (30 lignes = 10 personnes × 3 matières). Regrouper par name donne 10 groupes, et regrouper par subject donne 3 groupes.
GROUP BY — agréger par groupe
Quand tu écris GROUP BY colonne, les lignes qui partagent la même valeur dans cette colonne sont réunies dans un même groupe, et les fonctions d'agrégat sont calculées une fois par groupe. Avec SELECT name, AVG(score) FROM score GROUP BY name;, les 3 lignes ayant le même nom (une par matière) forment un groupe, et tu obtiens une ligne de moyenne par nom. Les seules « colonnes brutes » que tu peux mettre dans SELECT sont les colonnes nommées dans `GROUP BY` ; toute autre colonne doit être enveloppée dans une fonction d'agrégat (parce que sa valeur n'est pas unique au sein d'un groupe).
AVG(score) est calculé par groupe. Avec 10 personnes, le résultat fait 10 lignes.-- Nombre / moyenne / meilleure note par matière (3 groupes par subject)
SELECT
subject,
COUNT(*) AS row_count,
ROUND(AVG(score), 1) AS avg_score,
MAX(score) AS top_score
FROM score
GROUP BY subject;
HAVING — filtrer les résultats d'agrégat
Après un agrégat de groupe, tu veux parfois filtrer sur la valeur d'agrégat, comme « n'affiche que les groupes dont la moyenne est supérieure ou égale à 80 ». Tu ne peux pas faire cela avec WHERE. WHERE est une clause qui juge les lignes individuelles avant le regroupement, donc un agrégat de groupe comme AVG(score) n'a pas encore été calculé. C'est là qu'intervient `HAVING`. HAVING s'écrit après GROUP BY et juge sa condition sur les résultats d'agrégat des groupes. Écrire HAVING AVG(score) >= 80 ne garde que les groupes dont la moyenne est supérieure ou égale à 80.
GROUP BY agrège en 10 groupes, puis HAVING AVG(score) >= 80 juge les groupes déjà agrégés et ne garde que ceux qui satisfont la condition.-- Seulement les noms dont la moyenne dépasse 85 (HAVING juge la valeur d'agrégat)
SELECT
name,
ROUND(AVG(score), 2) AS avg_score
FROM score
GROUP BY name
HAVING AVG(score) > 85;
WHERE vs. HAVING — filtrer des lignes, ou filtrer des groupes
WHERE et HAVING sont tous deux des filtres, mais ils agissent à des moments différents. WHERE juge les lignes individuelles et les écarte avant le regroupement. HAVING juge par groupe et les écarte après le regroupement et l'agrégation. L'ordre d'exécution est FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY.
Tu peux aussi utiliser les deux à la fois. Dans ce cas, le déroulement est « restreindre les lignes ciblées avec WHERE, puis regrouper, puis filtrer les résultats d'agrégat avec HAVING ». Par exemple, pour obtenir « les personnes dont la moyenne par nom est de 80 ou plus, en ne considérant que Math et English », tu restreins les lignes avec WHERE subject IN ('Math','English') et tu restreins les groupes avec HAVING AVG(score) >= 80.
WHERE juge les lignes sur des colonnes brutes et les écarte avant le regroupement, tandis que HAVING juge les groupes sur des valeurs d'agrégat (AVG, etc.) et les écarte après le regroupement. Le point clé est où les choses sont écartées. Exemple : WHERE subject='Math' (filtre les lignes) et HAVING AVG(score)>=80 (filtre les groupes).-- Utiliser WHERE et HAVING ensemble
-- Exclure Science, ne garder que les noms dont la moyenne est de 80 ou plus
SELECT
name,
ROUND(AVG(score), 2) AS avg_two
FROM score
WHERE subject <> 'Science'
GROUP BY name
HAVING AVG(score) >= 80;
Vérification des connaissances
Répondez à chaque question une par une.
Question 2Quand tu veux extraire « uniquement les personnes dont la moyenne par nom est de 80 ou plus », dans quelle clause va la condition « 80 ou plus » ?
Question 3Quel énoncé décrit correctement la différence entre WHERE et HAVING ?