Aller au contenu
M06 · C. Manipuler les données

Calculer : fonctions, agrégats, GROUP BY, HAVING

Utiliser les fonctions du SGBD (texte, nombres, dates), résumer des lignes avec COUNT, SUM, AVG, MIN, MAX, regrouper avec GROUP BY et filtrer les groupes avec HAVING.

1Situer

Fin du mois à Souk Atlas : la présidente veut des chiffres. Combien de commandes ? Quel chiffre d'affaires par catégorie ? Quel est le prix moyen des poteries ? Quels clients ont commandé plus de deux fois ? On ne lit plus des lignes une par une : on les résume. C'est le travail des fonctions d'agrégation et de GROUP BY.

2Comprendre

GROUP BY : faire des paquets, puis calculer
1 · Tajine 180 · Plat 250 1 · Bol 45 · Théière 320 2 · Huile 120 · Savon 30 2 · Ghassoul 40 · Rose 55 3 · Babouches 150 · Tapis 1200 3 · Coussin 95 · Foulard 110 categorie_id · COUNT · AVG(prix) 1 · 4 · 198.75 2 · 4 · 61.25 3 · 4 · 388.75 ✖ HAVING

Les 12 produits, avec leur catégorie (1 Poterie, 2 Cosmétique, 3 Textile).

1 / 4

Les fonctions du SGBD

FamilleFonctions courantesExemple → résultat
TexteCONCAT, UPPER, LOWER, LENGTH, SUBSTRING, TRIMUPPER('fès') → FÈS
NombresROUND, ABS, CEIL, FLOORROUND(216.256, 2) → 216.26
DatesNOW, CURDATE, YEAR, MONTH, DAY, DATEDIFFYEAR('2025-03-09') → 2025
ConditionsIFNULL, IF, CASE WHENIFNULL(email, 'non renseigné')

Les fonctions d’agrégation

SELECT COUNT(*)          AS nb_produits,   -- 12
       SUM(stock)        AS pieces,        -- 368
       ROUND(AVG(prix),2) AS prix_moyen,   -- 216.25
       MIN(prix)         AS moins_cher,    -- 30
       MAX(prix)         AS plus_cher      -- 1200
FROM produits;

Regrouper : GROUP BY

SELECT categorie_id, COUNT(*) AS nb, ROUND(AVG(prix), 2) AS prix_moyen
FROM produits
GROUP BY categorie_id;

Résultat :

categorie_id | nb | prix_moyen
1            | 4  | 198.75
2            | 4  | 61.25
3            | 4  | 388.75

La catégorie 4 (Bijoux) n’a aucun produit : elle n’apparaît pas, puisqu’il n’y a aucune ligne à regrouper.

Filtrer les groupes : HAVING

Exemple simple

Le tri du linge

Avant de laver, on fait des tas par couleur (GROUP BY couleur), puis on compte les pièces de chaque tas (COUNT). Chaque tas devient une seule ligne : « blanc : 12 pièces ».

SELECT couleur, COUNT(*) FROM linge GROUP BY couleur;
Exemple simple

WHERE ou HAVING ?

WHERE trie les pièces avant de faire les tas (« seulement les vêtements, pas les draps »). HAVING regarde les tas déjà faits (« seulement les tas de plus de 10 pièces »).

3Manipuler

Répondez aux questions de la présidente avec des fonctions d'agrégation. Une requête par consigne : elle se coche quand le résultat est juste.
Pas à pas dans le lab ↗ La base de départ se crée dans votre navigateur (moteur SQL d’environ 700 Ko, chargé une fois).
Résultat

Le résultat de chaque requête s'affichera ici.

Consignes 0 / 5

  1. Le nombre total de pièces en stock (une seule valeur)
  2. Pour chaque categorie_id, le nombre de produits
  3. Pour chaque statut, le nombre de commandes
  4. Les client_id qui ont passé au moins 2 commandes, avec leur nombre de commandes
  5. Pour chaque commande (commande_id), son montant total : somme de quantite × prix_unitaire

4Pratiquer

Exercice 1 · Fonctions de texte et de date

Affichez pour chaque client : son nom complet en une colonne (« Amina BENALI »), et l'année de son inscription.

Voir le corrigé
SELECT CONCAT(prenom, ' ', UPPER(nom)) AS nom_complet,
       YEAR(date_inscription) AS annee
FROM clients;

Exercice 2 · Le chiffre d'affaires par mois

Calculez le chiffre d'affaires (quantité × prix unitaire) de chaque mois, en ignorant les commandes annulées.

Voir le corrigé
SELECT MONTH(o.date_commande) AS mois,
       SUM(l.quantite * l.prix_unitaire) AS ca
FROM commandes o
JOIN lignes_commande l ON l.commande_id = o.id
WHERE o.statut <> 'annulée'
GROUP BY MONTH(o.date_commande)
ORDER BY mois;

Exercice 3 · Corriger l'erreur

Pourquoi cette requête est-elle refusée ? SELECT categorie_id, AVG(prix) FROM produits WHERE AVG(prix) > 100 GROUP BY categorie_id;

Voir le corrigé
-- WHERE filtre les lignes AVANT le regroupement :
-- la moyenne n'existe pas encore. On filtre les groupes avec HAVING :
SELECT categorie_id, AVG(prix)
FROM produits
GROUP BY categorie_id
HAVING AVG(prix) > 100;

5Vérifier

1. Quelle est la différence entre COUNT(*) et COUNT(email) ?
2. Dans une requête avec GROUP BY, quelles colonnes peut-on mettre dans SELECT ?
3. Pour garder seulement les catégories qui ont plus de 3 produits, on écrit...