Exercices SQL corrigés : GROUP BY

Exercices SQL corrigés : GROUP BY

Mis à jour le

GROUP BY calcule un résumé par groupe : une ligne de résultat par valeur de la colonne. Ces 15 exercices vont du niveau 2 au niveau 3 ; ils utilisent la syntaxe de SQLite, le moteur SQL de SpeedQL.

Conseil : Toute colonne affichée sans agrégat doit apparaître dans le GROUP BY.

Relire la fiche « GROUP BY » de l’aide-mémoire

Exercice 1 · niveau 2

Pour chaque département, affiche le département et le nombre d'employés.

Table employees (8 lignes)
idnamedepartmentsalary
1AliceFinance32000
2BobIT41000
3ClaireFinance38000
4DavidHR29000
5EmmaIT50000
6FaridIT47000
7GaelleHR33000
8HugoFinance44000
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , COUNT(*)
FROM 
GROUP BY 
Voir la correction
SELECT department, COUNT(*)
FROM employees
GROUP BY department;

Résultat attendu (3 lignes) :

departmentCOUNT(*)
Finance3
HR2
IT3

Exercice 2 · niveau 2

Pour chaque département, affiche le département et le salaire moyen de ses employés.

Table employees (8 lignes)
idnamedepartmentsalary
1AliceFinance32000
2BobIT41000
3ClaireFinance38000
4DavidHR29000
5EmmaIT50000
6FaridIT47000
7GaelleHR33000
8HugoFinance44000
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , AVG()
FROM 
GROUP BY 
Voir la correction
SELECT department, AVG(salary)
FROM employees
GROUP BY department;

Résultat attendu (3 lignes) :

departmentAVG(salary)
Finance38000
HR31000
IT46000

Exercice 3 · niveau 2

Pour chaque département, affiche le département et le total des salaires versés.

Table employees (8 lignes)
idnamedepartmentsalary
1AliceFinance32000
2BobIT41000
3ClaireFinance38000
4DavidHR29000
5EmmaIT50000
6FaridIT47000
7GaelleHR33000
8HugoFinance44000
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , SUM()
FROM 
GROUP BY 
Voir la correction
SELECT department, SUM(salary)
FROM employees
GROUP BY department;

Résultat attendu (3 lignes) :

departmentSUM(salary)
Finance114000
HR62000
IT138000

Exercice 4 · niveau 2

Pour chaque catégorie, affiche la catégorie et le stock total de ses produits.

Table products (6 lignes)
idnamecategorypricestock
1KeyboardOffice2540
2MouseOffice150
3ScreenDisplay18012
4HeadsetAudio608
5WebcamOffice450
6SpeakerAudio3525
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , SUM()
FROM 
GROUP BY 
Voir la correction
SELECT category, SUM(stock)
FROM products
GROUP BY category;

Résultat attendu (3 lignes) :

categorySUM(stock)
Audio33
Display12
Office40

Exercice 5 · niveau 2

Pour chaque genre, affiche le genre et le nombre de films.

Table movies (10 lignes)
idtitlegenreyeardurationratingdirector_id
1Night TrainThriller20151187.81
2Blue HarborDrama20181027.12
3Paper Moon CityComedy2012956.45
4Silent PeakDrama20201318.23
5Last SignalSci-Fi20191427.51
6Summer KeysComedy2016885.94
7Iron GardenSci-Fi202112583
8Dust and GoldWestern20141106.82
9The Quiet HourDrama2022977.45
10Deep CurrentThriller20171056.9NULL
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , COUNT(*)
FROM 
GROUP BY 
Voir la correction
SELECT genre, COUNT(*)
FROM movies
GROUP BY genre;

Résultat attendu (5 lignes) :

genreCOUNT(*)
Comedy2
Drama3
Sci-Fi2
Thriller2
Western1

Exercice 6 · niveau 2

Pour chaque ville, affiche la ville et le nombre de membres.

Table members (6 lignes)
idnamecityjoined
1LenaLyon2022-01-15
2MarcParis2021-06-03
3NadiaLyon2023-03-20
4OscarLille2020-11-11
5PaulaParis2024-02-01
6QuentinNantes2023-09-09
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , COUNT(*)
FROM 
GROUP BY 
Voir la correction
SELECT city, COUNT(*)
FROM members
GROUP BY city;

Résultat attendu (4 lignes) :

cityCOUNT(*)
Lille1
Lyon2
Nantes1
Paris2

Exercice 7 · niveau 2

Pour chaque compagnie, affiche la compagnie, le nombre de vols et le prix moyen.

Table flights (12 lignes)
idairlineorigindestdepartsduration_minpriceseats_soldcapacity
1SkyJetCDGMAD2025-06-01 08:1012589150180
2AirNovaCDGLIS2025-06-01 11:40155120160170
3BlueWingLYSFCO2025-06-02 07:309575110150
4SkyJetMADCDG2025-06-02 18:2012095170180
5AirNovaBERCDG2025-06-03 09:05110105140160
6BlueWingNCEBER2025-06-03 13:5013014090150
7SkyJetCDGFCO2025-06-04 06:4513599175180
8AirNovaLISMAD2025-06-04 16:15756560120
9BlueWingFCOLYS2025-06-05 20:3010082130150
10SkyJetCDGBER2025-06-05 10:00105110120180
11AirNovaMADLIS2025-06-06 12:25807095120
12BlueWingLYSMAD2025-06-06 15:4011579100150
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , COUNT(*), AVG()
FROM 
GROUP BY 
Voir la correction
SELECT airline, COUNT(*), AVG(price)
FROM flights
GROUP BY airline;

Résultat attendu (3 lignes) :

airlineCOUNT(*)AVG(price)
AirNova490
BlueWing494
SkyJet498.25

Exercice 8 · niveau 2

Pour chaque genre, affiche le genre, le nombre de chansons et la durée moyenne en secondes.

Table songs (10 lignes)
idtitleartist_idgenreduration_sreleased
1Glass Heart1Pop2142019-04-12
2Low Tide1Pop1982021-06-01
3Rust2Rock2562008-09-30
4Wires2Rock3012015-02-14
5Sunday Market3Afrobeat2332020-11-20
6Palm Wine3Afrobeat2452022-03-03
7Alma4Latin1892013-07-07
8Brisa4Pop2052018-05-25
9Night Drive5Electro2762021-10-10
10Pulse5Electro2302023-01-15
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , COUNT(*), AVG()
FROM 
GROUP BY 
Voir la correction
SELECT genre, COUNT(*), AVG(duration_s)
FROM songs
GROUP BY genre;

Résultat attendu (5 lignes) :

genreCOUNT(*)AVG(duration_s)
Afrobeat2239
Electro2253
Latin1189
Pop3205.66666666666666
Rock2278.5

Exercice 9 · niveau 2

Pour chaque ville, affiche la ville, la plus haute température maximale relevée et la plus basse température minimale relevée.

Table readings (15 lignes)
idcitydaytemp_maxtemp_minrain_mm
1Paris2025-07-0124150
2Paris2025-07-0227170
3Paris2025-07-0322164.5
4Paris2025-07-04191412
5Paris2025-07-0523130
6Lyon2025-07-0126160
7Lyon2025-07-0229180
8Lyon2025-07-0331190
9Lyon2025-07-0424178.5
10Lyon2025-07-0522153
11Marseille2025-07-0130210
12Marseille2025-07-0232220
13Marseille2025-07-0333230
14Marseille2025-07-0429210
15Marseille2025-07-0528200
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , MAX(), MIN()
FROM 
GROUP BY 
Voir la correction
SELECT city, MAX(temp_max), MIN(temp_min)
FROM readings
GROUP BY city;

Résultat attendu (3 lignes) :

cityMAX(temp_max)MIN(temp_min)
Lyon3115
Marseille3320
Paris2713

Exercice 10 · niveau 2

Pour chaque type de chambre, affiche le type et le prix moyen arrondi à 1 décimale.

Table rooms (10 lignes)
idhotel_idtypeprice
11single70
21double95
32double130
42suite210
53single110
63double150
74double65
85double260
95suite480
105single190
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , ROUND(AVG(), )
FROM 
GROUP BY 
Voir la correction
SELECT type, ROUND(AVG(price), 1)
FROM rooms
GROUP BY type;

Résultat attendu (3 lignes) :

typeROUND(AVG(price), 1)
double140
single123.3
suite345

Exercice 11 · niveau 2

Pour chaque statut de commande, affiche le statut et le nombre de commandes.

Table orders (8 lignes)
idcustomer_idorder_datestatus
112025-01-05shipped
222025-01-12shipped
312025-02-03paid
432025-02-10cancelled
542025-02-20shipped
652025-03-02shipped
722025-03-15paid
832025-03-28shipped
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , COUNT(*)
FROM 
GROUP BY 
Voir la correction
SELECT status, COUNT(*)
FROM orders
GROUP BY status;

Résultat attendu (3 lignes) :

statusCOUNT(*)
cancelled1
paid2
shipped5

Exercice 12 · niveau 2

Pour chaque statut, affiche le statut et le nombre total d'heures des tâches.

Table tasks (10 lignes)
idproject_iddev_idtitlehoursstatusdone_on
111Landing page12done2025-03-10
213Data model20done2025-03-20
312Login8doingNULL
424ETL job16done2025-04-02
525CI pipeline6done2025-03-15
631Dashboard14todoNULL
733Report10done2025-04-25
842API18doingNULL
945Monitoring9todoNULL
1044Forecast22done2025-05-05
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , SUM()
FROM 
GROUP BY 
Voir la correction
SELECT status, SUM(hours)
FROM tasks
GROUP BY status;

Résultat attendu (3 lignes) :

statusSUM(hours)
doing26
done86
todo23

Exercice 13 · niveau 2

Pour chaque compte qui a des opérations, affiche le numéro du compte (account_id) et son solde (somme des montants).

Table transactions (14 lignes)
idaccount_idmade_onamountlabel
112025-01-022500salary
212025-01-05-60groceries
312025-01-12-800rent
422025-01-15500transfer
532025-01-031900salary
632025-01-20-120groceries
732025-02-01-950rent
842025-01-252100salary
942025-02-03-45restaurant
1012025-02-022600salary
1112025-02-06-75groceries
1252025-02-1030interest
1322025-02-15500transfer
1442025-02-18-600rent
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , SUM()
FROM 
GROUP BY 
Voir la correction
SELECT account_id, SUM(amount)
FROM transactions
GROUP BY account_id;

Résultat attendu (5 lignes) :

account_idSUM(amount)
14165
21000
3830
41455
530

Exercice 14 · niveau 3

Pour chaque département, affiche le département, le nombre d'employés et le salaire moyen, du salaire moyen le plus élevé au plus faible.

Table employees (8 lignes)
idnamedepartmentsalary
1AliceFinance32000
2BobIT41000
3ClaireFinance38000
4DavidHR29000
5EmmaIT50000
6FaridIT47000
7GaelleHR33000
8HugoFinance44000
Voir l’indice

Notions à utiliser : ORDER BY, LIMIT, COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT , COUNT(*), AVG()
FROM 
GROUP BY 
ORDER BY AVG() DESC
Voir la correction
SELECT department, COUNT(*), AVG(salary)
FROM employees
GROUP BY department
ORDER BY AVG(salary) DESC;

Résultat attendu (3 lignes, dans cet ordre) :

departmentCOUNT(*)AVG(salary)
IT346000
Finance338000
HR231000

Exercice 15 · niveau 3

Affiche le département dont le salaire moyen est le plus élevé.

Table employees (8 lignes)
idnamedepartmentsalary
1AliceFinance32000
2BobIT41000
3ClaireFinance38000
4DavidHR29000
5EmmaIT50000
6FaridIT47000
7GaelleHR33000
8HugoFinance44000
Voir l’indice

Notions à utiliser : ORDER BY, LIMIT, COUNT, SUM, AVG, MIN, MAX, GROUP BY.

Structure de la requête :

SELECT 
FROM 
GROUP BY 
ORDER BY AVG() DESC
LIMIT 
Voir la correction
SELECT department
FROM employees
GROUP BY department
ORDER BY AVG(salary) DESC
LIMIT 1;

Résultat attendu (1 ligne) :

department
IT

S’entraîner avec correction automatique

Dans SpeedQL, tu écris ta requête et elle est vérifiée tout de suite, sur ces tables puis sur un jeu de données caché.

S’entraîner sur les 27 questions « GROUP BY »