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
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"_.
-- 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 :
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 :
- une des colonnes de regroupement (par exemple
department_id,d.name), ou - à l'intérieur d'une fonction d'agrégation (par exemple
AVG(salary),COUNT(*)).
-- 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
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.
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
Pour chaque département (departments.name), calculez le salaire moyen (AVG(salary)) de ses employés, triés du plus élevé au plus bas.
Afficher l'indice
AVG(e.salary) comme agrégat, GROUP BY d.name, ORDER BY moyenne DESC.
Solution disponible après 3 tentatives