Terminale · Bases de données et SQL

SQL : compter et calculer avec les agrégations

Combien de résultats sont enregistrés ? Combien possèdent vraiment un score ? Ces deux questions peuvent produire des réponses différentes. Les fonctions d’agrégation résument des lignes, à condition de comprendre exactement lesquelles et quelles valeurs elles utilisent.

SofienAvec SofienIngénieur et enseignant en informatique
Dans ce chapitre

Un cap pour ce chapitre

Ce que vous saurez faire

  • Utiliser COUNT, SUM, AVG, MIN et MAX.
  • Appliquer un filtre avant une agrégation.
  • Distinguer zéro, absence de valeur et absence de ligne.
Les bases utiles pour commencer

Résumer un ensemble de lignes

La relation Resultat(id_resultat, prenom, score) décrit les résultats fictifs d’un défi. Le symbole NULL indique un score non renseigné ; ce n’est pas un score égal à zéro. Nous travaillons sur l’ensemble complet présenté ci-dessous.

id_resultatprenomscore
1Lina12
2Noé0
3Sara18
4AdamNULL
5Lina12

Une agrégation produit une information globale : nombre, somme, moyenne ou extremum. Sans regroupement, les fonctions appliquées à un ensemble de lignes donnent un résultat de synthèse. Les clauses GROUP BY et HAVING ne sont pas nécessaires aux attendus de ce chapitre.

Compter les lignes ou les valeurs connues

COUNT(*) compte les lignes, y compris celles dont le score manque. Ici, son résultat vaut 5. COUNT(score) compte les valeurs de score non NULL : il vaut 4. La valeur zéro de Noé est bien présente et doit être comptée. Oublier zéro reviendrait à changer la question.

COUNT(DISTINCT prenom) compte les prénoms différents renseignés. Avec nos données, Lina ne compte qu’une fois dans cette question, alors que ses deux résultats restent deux lignes distinctes. Avant d’écrire COUNT, formulez ce qui doit être dénombré : personnes, lignes, valeurs connues ou valeurs différentes.

La question « combien de personnes ? » n’est pas équivalente au nombre de prénoms distincts. Deux personnes peuvent partager un prénom et une personne peut avoir plusieurs résultats. Notre relation identifie des résultats, pas nécessairement des personnes. Un compte doit donc être accompagné de son unité : lignes de résultats, valeurs de score ou prénoms distincts.

Somme, moyenne et extrema

SUM(score) additionne les scores connus : 12 + 0 + 18 + 12 = 42. AVG(score) divise cette somme par le nombre de scores connus, soit 4 : la moyenne vaut 10,5. MIN(score) vaut 0 et MAX(score) vaut 18. La ligne d’Adam n’est pas traitée comme un résultat nul.

Si aucune valeur connue n’est disponible, SUM, AVG, MIN et MAX produisent NULL dans le comportement SQL étudié ici. COUNT renvoie zéro. Une absence de résultat renseigné ne permet pas d’inventer une moyenne égale à zéro : zéro serait une information numérique différente.

SELECT COUNT(*), COUNT(score),
       SUM(score), AVG(score),
       MIN(score), MAX(score)
FROM Resultat;

Le zéro de Noé ne contribue pas à la somme, mais il augmente le nombre de scores connus utilisé au dénominateur. C’est pourquoi retirer ce zéro laisse la somme à 42 mais augmente la moyenne de 10,5 à 14. Une ligne peut donc ne rien ajouter à SUM tout en influençant AVG et COUNT.

Filtrer d’abord, agréger ensuite

WHERE limite les lignes prises en compte avant le calcul. Avec WHERE score >= 10, on retient 12, 18 et 12. La somme reste 42 mais la moyenne devient 14, car le zéro est exclu. Le score manquant ne satisfait pas cette comparaison et ne passe pas le filtre.

Ajouter une colonne ordinaire sans expliquer son lien avec l’agrégation peut créer une requête ambiguë ou refusée selon le SGBD. Pour ce chapitre, on utilise des agrégations globales clairement définies. Les alias comme AS moyenne peuvent ensuite rendre les titres du résultat lisibles sans modifier les valeurs calculées.

Exemple suivi : filtrer une frontière et ses effets

Avec WHERE score >= 12, les trois scores retenus sont 12,18,12. On obtient COUNT(*)=3, COUNT(score)=3, somme 42, moyenne 14, minimum 12 et maximum 18. Avec un seuil 13, seul 18 reste : les six résultats deviennent 1,1,18,18,18,18.

Le changement vient de l’inclusion des deux valeurs exactement égales à 12. Pour vérifier un filtre, testez donc la frontière et une valeur juste supérieure. La présence initiale de NULL n’entraîne pas un score fictif : une comparaison numérique ordinaire ne le retient pas. Si l’on veut rechercher les lignes sans score, le test approprié est score IS NULL, et non une égalité à zéro.

Distinguer vide, inconnu et valeurs distinctes

Une requête globale d’agrégation sans regroupement produit une ligne de synthèse même lorsque le filtre ne retient aucune ligne source. Avec un seuil supérieur à 18, les deux COUNT valent zéro, tandis que SUM, AVG, MIN et MAX valent NULL dans le comportement étudié. Ce n’est pas une ligne ordinaire de résultat sportif, mais une synthèse de l’ensemble vide.

La ligne d’Adam seule illustre une autre situation : une ligne existe, mais aucun score n’est connu. COUNT(*) vaut alors 1 et COUNT(score) vaut 0. Enfin, compter les scores distincts de toute la relation revient à retenir 0,12,18 : trois valeurs. Cela ne compte ni les quatre scores renseignés ni les cinq lignes. Avant une agrégation, reformulez exactement la population retenue et la grandeur calculée.

À vous de faire varier les choses

Qui entre dans le calcul ?

Activez un filtre puis changez son seuil. Comparez le nombre de lignes, le nombre de scores connus et la moyenne ; testez un résultat vide.

Lire le résultat de l’expérience initiale

5 ligne(s), 4 score(s) connu(s).

Le zéro est une valeur connue. NULL est exclu des agrégations sur score et ne passe pas une comparaison numérique ordinaire.

id_resultatprenomscore retenu
1Lina12
2Noé0
3Sara18
4AdamNULL
5Lina12

Un résumé n’a de sens que si l’on sait exactement quelles lignes et quelles valeurs y participent.

De la compréhension à l’autonomie

À vous de résoudre

Cherchez d’abord par vous-même. Vérifiez les résultats demandés, utilisez les indices si nécessaire, puis comparez votre méthode à la correction.

Exercice 1 · Comprendre#

Deux comptages différents

Donnez COUNT(*) et COUNT(score) sur la relation fournie. Le score zéro est-il compté par COUNT(score) ?

Indice 1

Une seule ligne possède un score NULL.

Indice 2

Zéro est une valeur numérique connue.

Comprendre la correction

COUNT(*) vaut 5 et COUNT(score) vaut 4. Le zéro de Noé est compté ; seule la valeur NULL est exclue du second calcul. Les deux agrégations répondent à deux questions différentes plutôt qu’à deux versions approximatives du même résultat.

Exercice 2 · Calculer#

La bonne moyenne

Calculez AVG(score) sur toutes les lignes, puis avec WHERE score >= 10. Justifiez les dénominateurs.

Indice 1

Sans filtre, quatre scores sont connus.

Indice 2

Avec le filtre, le score zéro disparaît.

Comprendre la correction

Sans filtre, la moyenne vaut 42 / 4 = 10,5. Avec le filtre, elle vaut 42 / 3 = 14. On ne divise jamais par cinq dans ces deux cas, car NULL ne représente pas un score connu. Le filtre change l’ensemble résumé.

Exercice 3 · Corriger#

Remplacer un manque par zéro

Un élève affirme qu’Adam a obtenu zéro parce que son score est NULL. Pourquoi cette interprétation modifie-t-elle les données ?

Indice 1

Aucune valeur numérique n’est fournie pour Adam.

Indice 2

Une note nulle et une note non renseignée ne racontent pas le même fait.

Comprendre la correction

NULL signale une absence de valeur dans ce modèle. Lui attribuer zéro invente un résultat connu et modifie notamment la moyenne. Il faut conserver la distinction et rechercher la raison de l’absence si elle est nécessaire à l’analyse.

Exercice 4 · Justifier#

Un filtre ne garde personne

Que valent COUNT(*) et AVG(score) avec WHERE score > 20 sur les données fournies ? Pourquoi leurs résultats diffèrent-ils ?

Indice 1

Aucun score ne dépasse 20.

Indice 2

Un nombre de lignes est défini même lorsqu’il n’y en a aucune.

Comprendre la correction

COUNT(*) vaut 0 : aucune ligne ne passe le filtre. AVG(score) vaut NULL, car aucune moyenne de valeurs disponibles ne peut être calculée. Zéro pour la moyenne signifierait un score moyen connu, ce qui serait une information incorrecte.

Exercice 5 · Approfondir et transférer#

Deux seuils voisins

Calculez COUNT(score), SUM(score) et AVG(score) pour les filtres score >= 12 puis score >= 13. Expliquez quels tuples disparaissent et pourquoi la moyenne augmente alors que la somme baisse.

Indice 1

Deux résultats valent exactement 12.

Indice 2

Le score 18 reste dans les deux ensembles.

Comprendre la correction

Au seuil 12, les résultats sont 3,42,14. Au seuil 13, ils sont 1,18,18. Les deux scores de 12 disparaissent. La moyenne des valeurs restantes peut augmenter malgré une somme plus faible, parce que le dénominateur passe de trois à un.

Exercice 6 · Approfondir et transférer#

Une ligne dont le score manque

On filtre uniquement Adam avec WHERE prenom='Adam'. Donnez COUNT(*), COUNT(score) et AVG(score). Comparez à un filtre ne retenant aucune ligne. Quel test permet de cibler les scores manquants ?

Indice 1

Une ligne peut être présente sans valeur numérique connue.

Indice 2

Le test de NULL ne s’écrit pas comme une comparaison avec zéro.

Comprendre la correction

Pour Adam, les résultats sont 1,0,NULL. Pour un ensemble vide, ils sont 0,0,NULL. Les deux situations ont aucune valeur connue mais un nombre de lignes différent. WHERE score IS NULL permet de cibler les scores absents.

Exercice 7 · Approfondir et transférer#

Choisir ce qui est compté

Sur la relation entière, donnez le nombre de lignes, de scores connus, de scores distincts connus et de prénoms distincts. Dites lequel de ces nombres peut être affirmé comme nombre de personnes physiques sans autre information.

Indice 1

Les scores distincts sont 0,12,18.

Indice 2

Le prénom Lina apparaît deux fois sans identifiant de personne dans cette relation.

Comprendre la correction

On obtient 5 lignes, 4 scores connus, 3 scores distincts et 4 prénoms distincts. Aucun ne permet à lui seul d’affirmer le nombre de personnes physiques : la relation identifie des résultats et les prénoms peuvent être partagés. Il faudrait un identifiant de personne et une règle sur la participation.

Les erreurs qui méritent un détour

Diviser la somme par le nombre de lignes alors que des valeurs manquent.
AVG porte sur les valeurs non NULL. Le dénominateur doit correspondre aux valeurs additionnées.
Confondre un résultat nul avec une absence de résultat.
0 est une valeur ; NULL exprime ici que la valeur n’est pas renseignée ou que l’agrégation n’est pas définie sur les données disponibles.

La fiche à garder

L’essentiel à retenir

  • COUNT(*) compte les lignes, COUNT(attribut) ses valeurs connues.
  • Les agrégations utilisent les lignes retenues par WHERE.
  • NULL ne se remplace pas automatiquement par zéro.

Cette notion au bac

Retrouvez ces idées dans un sujet complet, avec des indices, une correction expliquée et des ateliers.

Le prochain pas

Retrouver le catalogue de Terminale

Ce chapitre s’appuie sur le programme officiel de Terminale (PDF, nouvel onglet). Les explications et exercices sont proposés pour l’apprentissage.