Passer au contenu principal
eLearner.app
Module 3 · Leçon 3 sur 411/57 dans le cours~10 min
Leçons du module (3/4)

Grouper avec GROUP BY

Dans le module 2, vous avez appris que COUNT(*), AVG(...), SUM(...) réduisent tous lignes en une seule ligne de résultats. Mais que se passe-t-il si vous voulez un salaire moyen pour chaque département, pas pour toute l'entreprise ? Vous voulez une ligne par groupe. C'est le travail de GROUP BY.

La syntaxe

SQL
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM   table
GROUP BY grouping_column;

Lire en anglais : _ "diviser les lignes en groupes partageant la même valeur de grouping_column, et pour chaque groupe calculer l'agrégat"_.

SQL
-- Average salary per department:
SELECT department_id, AVG(salary) AS average
FROM   employees
GROUP BY department_id;

Le résultat comporte une ligne pour chaque department_id distinct trouvé dans employees. Vous obtiendrez 5 lignes : une pour chacun des 4 départements (1, 2, 3, 4) plus un pour NULL (Andrea Costa).

Avec JOIN pour des noms lisibles

Souvent, vous souhaitez regrouper par department_id mais afficher le nom du département. Vous combinez GROUP BY avec un JOIN :

SQL
SELECT d.name AS department,
       COUNT(*)    AS count,
       AVG(e.salary) AS average_salary
FROM   employees   AS e
JOIN   departments AS d ON e.department_id = d.id
GROUP BY d.name
ORDER BY count DESC;

Il s'agit d'une requête de business intelligence à part entière : en trois lignes, elle vous indique combien d'employés chaque département compte et combien ils gagnent moyenne, triée du plus grand au plus petit.

La règle d'or

Lorsque vous utilisez GROUP BY, chaque colonne du SELECT doit être :

  1. une des colonnes de regroupement (par exemple department_id, d.name), ou
  2. à l'intérieur d'une fonction d'agrégation (par exemple AVG(salary), COUNT(*)).
SQL
-- ERROR: first_name is neither in GROUP BY nor inside an aggregate
SELECT department_id, first_name, AVG(salary)
FROM   employees
GROUP BY department_id;

PostgreSQL renvoie une erreur explicite ("la colonne doit apparaître dans le GROUP BY clause ou être utilisé dans une fonction d'agrégation"). C'est un début de semaine courant erreur : si vous le voyez, arrêtez-vous et demandez-vous "quelle est la valeur de first_name pour un groupe de 3 personnes ?" — il n'y a pas de réponse unique, et c'est pour ça que le moteur refuse.

Essayez-le

Exercice#sql.m3.l3.e1
Tentatives : 0Chargement…

Pour chaque département, calculez le nombre d'employés qu'il contient. Renvoie deux colonnes : le nom du service (departments.name) et le nombre d'employés. Une ligne par département.

Chargement de l'éditeur…
Afficher l'indice

Agrégez avec COUNT(*) et regroupez par d.name. Le SELECT doit contenir uniquement la colonne de regroupement et l'agrégat.

Solution disponible après 3 tentatives

Exercice de révision

Exercice#sql.m3.l3.e2
Tentatives : 0Chargement…

Pour chaque département (departments.name), calculez le salaire moyen (AVG(salary)) de ses employés, triés du plus élevé au plus bas.

Chargement de l'éditeur…
Afficher l'indice

AVG(e.salary) comme agrégat, GROUP BY d.name, ORDER BY moyenne DESC.

Solution disponible après 3 tentatives