Introduction : Pourquoi regrouper des données ?
Imagine que tu as une base de données d'un magasin en ligne avec des milliers de commandes. Tu veux savoir : quel est le montant total des ventes par catégorie de produit ? Ou encore : quels clients ont passé plus de 5 commandes ? Pour répondre à ce type de questions, tu ne peux pas te contenter de simples SELECT et WHERE. Tu dois agréger et regrouper tes données. C'est exactement le rôle du duo GROUP BY et HAVING, deux clauses SQL fondamentales que tu vas rencontrer en NSI et dans tes projets.
Les fonctions d'agrégation : les outils de calcul
Avant de regrouper, il faut savoir quoi calculer sur chaque groupe. Les fonctions d'agrégation font ce travail. Les principales sont :
- COUNT() : Compte le nombre de lignes.
- SUM() : Fait la somme des valeurs d'une colonne numérique.
- AVG() : Calcule la moyenne.
- MIN() et MAX() : Trouvent la valeur minimale et maximale.
Utilisées seules, elles donnent un résultat pour toute la table. Par exemple, SELECT COUNT(*) FROM commandes; te donnera le nombre total de commandes. Mais la magie opère quand on les combine avec GROUP BY.
La clause GROUP BY : le regroupement
La clause GROUP BY permet de scinder ta table en sous-ensembles (groupes) en fonction des valeurs identiques dans une ou plusieurs colonnes. La fonction d'agrégation est ensuite appliquée sur chaque groupe indépendamment.
Syntaxe et premier exemple
La structure de base est :SELECT colonne_a_grouper, FONCTION_AGREGAT(autre_colonne)
FROM table
GROUP BY colonne_a_grouper;
Prenons une table commandes(id, client_id, montant, date).
Question : Quel est le montant total dépensé par chaque client ?
Requête :SELECT client_id, SUM(montant) AS total_depense
FROM commandes
GROUP BY client_id;
Le moteur SQL : 1) Regroupe toutes les lignes ayant le même client_id. 2) Pour chaque groupe (chaque client), calcule la somme des montant. 3) Renvoie une ligne par client avec son ID et son total.
Regrouper sur plusieurs colonnes
Tu peux grouper sur plusieurs critères. Par exemple, avec une table ventes(produit, ville, quantite) :SELECT produit, ville, SUM(quantite)
FROM ventes
GROUP BY produit, ville;
Cette requête te donnera la quantité totale vendue pour chaque combinaison produit/ville.
La clause HAVING : le filtre des groupes
Maintenant, supposons que tu veuilles ne garder que les clients ayant dépensé plus de 1000€ au total. Tu pourrais être tenté d'utiliser WHERE total_depense > 1000, mais cela ne fonctionnera pas. Pourquoi ? Parce que WHERE filtre les lignes avant le regroupement et le calcul des agrégats. Ici, nous voulons filtrer après, sur le résultat de l'agrégation.
C'est le rôle de HAVING. Elle filtre les résultats après l'application de GROUP BY.
Différence cruciale : WHERE vs HAVING
- WHERE : S'applique aux lignes individuelles de la table source. Utilise les colonnes originales. Se place avant
GROUP BY. - HAVING : S'applique aux groupes créés. Utilise presque toujours une fonction d'agrégation ou la colonne de regroupement. Se place après
GROUP BY.
Exemple complet : Clients avec plus de 5 commandes et un total > 1000€.SELECT client_id, COUNT(*) AS nb_commandes, SUM(montant) AS total
FROM commandes
GROUP BY client_id
HAVING COUNT(*) > 5 AND SUM(montant) > 1000;
Note comment on utilise les fonctions COUNT() et SUM() directement dans la condition HAVING.
Mise en pratique avec un projet type NSI
Imaginons que tu doives analyser les données d'une bibliothèque pour ton projet NSI. Tu as une table emprunts(livre_id, usager_id, date_emprunt, duree_jours).
Objectif 1 : Trouver les 5 livres les plus empruntés.SELECT livre_id, COUNT(*) AS fois_emprunte
FROM emprunts
GROUP BY livre_id
ORDER BY fois_emprunte DESC
LIMIT 5;
Objectif 2 : Identifier les usagers "assidus" ayant emprunté plus de 10 livres différents.SELECT usager_id, COUNT(DISTINCT livre_id) AS livres_différents
FROM emprunts
GROUP BY usager_id
HAVING COUNT(DISTINCT livre_id) > 10;
Ici, on utilise COUNT(DISTINCT ...) pour éviter de compter deux fois le même livre emprunté par la même personne.
Objectif 3 : Calculer la durée moyenne d'emprunt par usager, mais seulement pour ceux ayant fait plus de 3 emprunts.SELECT usager_id, AVG(duree_jours) AS duree_moyenne
FROM emprunts
GROUP BY usager_id
HAVING COUNT(*) > 3;
Pièges à éviter et bonnes pratiques
- Colonnes dans le SELECT : Toute colonne dans le
SELECTqui n'est pas dans une fonction d'agrégation doit apparaître dans leGROUP BY. Sinon, SQL ne saura pas quelle valeur afficher pour le groupe. - Alias dans HAVING : Certains SGBD (comme MySQL) permettent d'utiliser l'alias défini dans le
SELECT(ex:HAVING total > 1000). Pour la portabilité et la clarté, privilégie l'utilisation de la fonction complète (HAVING SUM(montant) > 1000). - Ordre des clauses : L'ordre est logique et imposé :
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT. Pense à "W G H O L" comme moyen mnémotechnique (Where, Group by, Having, Order by, Limit).
Le savais-tu ? En théorie des bases de données,
GROUP BYcorrespond à l'opérateur d'algèbre relationnelle de regroupement (γ). C'est une opération fondamentale pour transformer des données brutes en informations synthétiques.
Conclusion
Maîtriser GROUP BY et HAVING, c'est passer de la simple consultation de données à leur analyse et synthèse. Tu peux désormais répondre à des questions complexes du type "combien par...", "quelle moyenne pour chaque...", "qui a dépassé tel seuil...". Ces clauses sont indispensables pour tout projet NSI impliquant une base de données, que ce soit pour un site web, une application de gestion ou une analyse de dataset. À toi de jouer : ouvre ton SGBD, crée une petite table de test et expérimente !
