Agrégation
Agrégation
L'idée d'agrégation est de pouvoir calculer des synthèses à partir des données récupérées d'une requête SQL.
Par exemple, je veux calculer la somme de valeurs extraites d'une requête, ou bien compter le nombre de lignes retournées.
Il y a plusieurs opérations d'agrégation possibles :
Compter :
count
La somme :
sum
La moyenne :
avg
Le minimum :
min
Le maximum :
max
À noter, si j'utilise un opérateur d'agrégation, le résultat sortant ne contiendra que la valeur d'agrégation, et pas toutes les lignes demandées par la requête select
!
Par exemple, je veux connaître le nombre d'interventions et le budget moyen qui ont eu lieu dans l'Eure :
Le résultat est :
123
339.390244
À noter, qu'un plan d'action implicite a été créé par notre SGBDR :
Une table temporaire contenant les lignes qui remplissent notre clause
where
est construitCette table est traversée, en calculant les valeurs synthèses
Exemple : count
et distinct
count
et distinct
Je veux savoir le nombre total d'intervenants qui sont intervenus en novembre 2022.
Pour cela, il y a plusieurs jointures à faire :
on commence par récupérer tous les événements de cette période (la table
action_event
)pour chaque événement, on peut récupérer les intervenants, en faisant un produit cartésien avec
event_animator
(avec la contrainte que leeventId
soit identique)
Je fais un premier teste de construction d'une requête SQL :
Résultat : 3397 lignes
ALERTE ! ALERTE ! ALERTE !
Ici il y a eu une mauvaise interprétation des données, ou bien de la question !
Je veux connaître le nombre d'intervenants, alors cette requête me donne le nombre d'interventions par chaque intervenant !
Vous ne voyez pas trop la différence ? Dans ce cas, je conseille toujours de visualiser les données avant de procéder avec l'agrégation.
Commençons juste par visualiser l'ID de l'intervenant et les dates :
Qui retourne :
5ff8c7cfbf559e0012e3123c
2022-11-18 09:00:00
5ff8c7cfbf559e0012e3123c
2022-11-25 09:00:00
5ff8b8489b4af50013c919cd
2022-11-10 10:00:00
5ff8b8489b4af50013c919cd
2022-11-17 10:00:00
5ff8b8489b4af50013c919cd
2022-11-24 10:00:00
60cb4a6500c00100129f6de2
2022-11-09 16:00:00
60cb4a6500c00100129f6de2
2022-11-16 16:00:00
60cb4a6500c00100129f6de2
2022-11-23 16:00:00
60cb4a6500c00100129f6de2
2022-11-30 16:00:00
5ff8c5bf4875ad00136fbeb7
2022-11-07 14:15:00
61fd46f0f3cd6f0019f27645
2022-11-08 14:00:00
61fd46f0f3cd6f0019f27645
2022-11-15 14:00:00
5ff8b88c4875ad00136fbce3
2022-11-22 14:00:00
61fd46f0f3cd6f0019f27645
2022-11-29 14:00:00
...
...
Ah oui ! On voit toute suite que l'intervenant 5ff8c7cfbf559e0012e3123c
intervient dans plusieurs événements pendant la période. Et, il sera compté 5 fois dans notre agrégation !
On peut utiliser distinct
pour corriger l'erreur :
Le résultat : 772 intervenants
Attention aux détails :
On utilise l'opérateur
distinct
uniquement sur l'attributanimatorId
, car distinct agit sur l'ensemble des attributs. Si on avait gardéstartUtc
,distinct
n'aurait pas changé le résultatEnsuite, on compte le nombre de résultats avec
count
Groupes
Je sais maintenant qu'il y a eu 772 intervenants qui ont travaillé le mois de novembre 2022. En revanche, maintenant, je veux construire un rapport qui détaille le nombre total d'événements de chaque intervenant.
Dans ce cas, il serait utile de grouper les résultats de la requête précédente, et compter le nombre de lignes par groupe. On utilise la clause group by
:
Le résultat :
5f1fd5776ecbce00107beb84
4
5f3a82f408d0f10010d8eafe
4
5f3b9e0f6ecbce00107bec30
26
5f3d14af08d0f10010d8eb2a
19
5f3d154f6ecbce00107bec8d
15
...
...
Attention aux détails :
la clause
group by
peut agir sur plusieurs attributs (commedistinct
), et va créer des groupes, des tuples identiquesj'enlève donc
distinct
de la requête
Bien sûr, notre résultat n'est pas très intéressant pour notre rapport. Idéalement, je récupérerai les noms/prénoms des intervenants pour mon rapport, qui demande d'autres jointures :
Exercice avec groupes
Je veux générer un rapport qui me sort les salaires à payer pour chaque intervenant pour le mois de novembre 2022. Le rapport doit lister :
Le prénom et nom de l'intervenant
Le nombre d'heures travaillé
Le total à lui payer
L'intervenant est payé par heure. Donc, pour un intervenant payé à 25 € l'heure, pour événement de 2 heures, l'intervenant sera payé 50 €.
Astuces et feuille de route :
Commencez par analyser le schéma :
Quel(s) attribut(s) décrive(nt) la durée d'un événement ?
On récupère où son tarif horaire ?
Essayez d’abord construire une requête qui indique le début et la fin de chaque événement de chaque intervenant, en affichant son tarif horaire
Ensuite, vous arrivez à transformer le début et la fin de chaque événement en nombre d'heures ? Astuce : regardez les fonctions
timediff
ettime_to_sec
Ensuite, vous arrivez à calculer la somme à payer pour chaque événement ?
Ensuite, essayez de calculer la synthèse (agrégation) pour chaque intervenant
La clause having
having
Parfois, on aimerait appliquer un deuxième phase de filtrage sur le résultat d'une synthèse.
Par exemple, imaginons qu'il y a une règle qui interdit le travail de plus que 35 heures par mois. On aimerait sortir un rapport de tous les intervenants qui ont travaillé plus que 35 heures pour la période de novembre 2022.
On peut d'abord s'inspirer de l'exercice précédent pour sortir le nombre d'heures travaillées par chaque intervenant :
5f1fd5776ecbce00107beb84
Antoinette
Mercier
4.00
5f3a82f408d0f10010d8eafe
Amarande
Paul
4.00
5f3b9e0f6ecbce00107bec30
Landry
Fernandez
71.00
5f3d14af08d0f10010d8eb2a
Alcime
Dubois
36.00
5f3d154f6ecbce00107bec8d
Herluin
Royer
51.00
On peut ensuite appliquer un deuxième filtre sur ce résultat avec la clause having
:
5f3b9e0f6ecbce00107bec30
Landry
Fernandez
71.00
5f3d14af08d0f10010d8eb2a
Alcime
Dubois
36.00
5f3d154f6ecbce00107bec8d
Herluin
Royer
51.00
..
..
..
..
Les valeurs null
et l'agrégation
null
et l'agrégationAttention ! Toutes les fonctions sauf count
ignorent les valeurs null
.
Exercices
Les exercices suivants sont basés sur la base de données SAKILA, une base de données de test fourni par MySQL.
Question 1
Affichez la liste des noms de famille des acteurs, et comptez le nombre d’acteurs qui partagent le même nom de famille. Appelez cette deuxième colonne « shared_surname »
Question 2
Affichez uniquement la liste des acteurs qui partagent le même nom de famille.
Question 3
Calculez le prix de location moyen pour chaque genre de film. Quel est le prix moyen pour le genre Drama
?
Question 4
Combien de genres ont un prix moyen supérieur à 3€ ?
Dernière mise à jour