Aller au contenu principal

Fonctions d'agrégation

Définition

Une agrégation est une opération qui permet de combiner plusieurs valeurs de données en une seule valeur résumée. Les opérations d'agrégation sont souvent utilisées en combinaison avec la clause group by pour regrouper les données selon des critères spécifiques avant de les résumer.

Compter​

L'opérateur count Compte le nombre d'enregistrements dans un ensemble de données.

Exercice : Compter le nombre d'adhérents.

select count(*) from adherent
>> 2439

On peut compter sur n'importe quelle colonne, dans ce cas, pour ne pas avoir à choisir on utilise le caractère joker *.

attention

Attention ! Si on compte sur une colonne seules les lignes avec une valeur non nulle seront comptées.

Exercice : Compter le nombre d'adhérent dont le codepostal est non null.

select count(codepostal) from adherent;
>> 2438

Exercice : Compter le nombre d'articles de la famille 02CHOU.

select count(*) from article
where famille_code = '02CHOU'
>> 29

distinct​

En ajoutant le mot clé distinct l'opération s'effectue sur les valeurs uniques d'une ou de plusieurs colonnes.select codepostal, count(case when genre = 1 then 1 end) as nb_hommes, count(case when genre = 2 then 1 end) as nb_femmes from adherent group by codepostal;

Exercice : Afficher le nombre de codes postaux différents trouvés dans la table adhérent.

select count(distinct codepostal) from adherent
>> 11

[!WARNING] Attention ! Sans distinct, count(codepostal) compte toutes les lignes de la colonne codepostal dont la valeur est non nulle. Dans notre cas pratiquement tous les adhérents (2438/2439).

Regroupement​

la clause group by permet de choisir un ou plusieurs niveau de regroupement.

select codepostal, count(*)
from adherent
group by codepostal;
codepostalcount
88210178
88650195
8858097
88430131
88520127
88110210
88420158
88480245
88490261
88100650
88470187

Alias de colonne​

Il est possible de donner un nom spécifique à n'importe qu'elle colonne y compris (et surtout) les colonnes d'agrégations avec le mot clé as.

select codepostal, count(*) as nb_adherents
from adherent
group by codepostal;

Filtre​

Il est également possible d'ajouter une condition where à une seule colonne uniquement. C’est souvent plus lisible et performant que de faire un CASE WHEN imbriqué. Cela permet de faire des agrégations différenciées par colonne.

Exercice : Afficher le nombre d'adhérent par code postal ET par genre de telle façon d'avoir UNE ligne par code postal et deux colonnes une pour les hommes et l'autre pour les femmes.

Avec la clause group by une ligne différente est générée par combinaison de colonnes.

select codepostal, genre, count(*) as nb_adherents
from adherent
group by codepostal, genre
codepostalgenrenb_adherents
88580 2 51
88650 1 114
88430 2 54
88520 1 68
88110 1 103
88100 1 345
88110 2 107
.........
select codepostal,
count(*) filter (where genre = 1) as nb_hommes,
count(*) filter (where genre = 2) as nb_femmes
from adherent
group by codepostal
codepostalnb_hommes nb_femmes
882109484
8865011481
885804651
884307754
885206859
88110103107
884208276
88480135110
88490128133
88100345305
8847010384

Équivalent avec des case when

select codepostal,
count(case when genre = 1 then 1 end) as nb_hommes,
count(case when genre = 2 then 1 end) as nb_femmes
from adherent
group by codepostal;

Somme​

Calcule la somme des valeurs d'une colonne numérique.

SELECT SUM(vente) FROM ticket;

Exercice : Calculer le chiffre d’affaires global. (1 914 792.40)

select round(sum(quantite * prix_unitaire), 2) as chiffre_affaire from ligne;
>> 1914792.40

select sum(round(quantite * prix_unitaire, 2)) as chiffre_affaire from ligne;
>> 1915049.36

L'arrondi de la somme n'est pas égal à la somme des arrondis.

Moyenne​

Calcule la moyenne des valeurs d'une colonne numérique.

select avg(prix) from article;

Maximum​

Retourne la valeur maximale dans une colonne.

select max(age) from adherent;

Une autre solution consiste à trier la colonne est de limiter le résultat à une seule ligne

Exercice : Afficher l'article le plus cher (avec son prix).

select article, prix
from article
order by prix desc limit 1;
>> Pistache 63 €

Minimum​

Retourne la valeur minimale dans une colonne.

select min(age) from adherent;

Une autre solution consiste à trier la colonne est de limiter le résultat à une seule ligne

Afficher l'article le moins cher (avec son prix). (Courgette Mini Fleur 0.3)

select article, prix
from article
order by prix asc limit 1;

Exercice : Pour chaque adhérent quel est la date de son premier et de son dernier ticket.

Une valeur​

Avec la fonction any_value la colonne prend une valeur de la colonne sans distinction particulière.

select codepostal, any_value(nom)
from adherent
group by codepostal;
codepostalnom
88480Fievet
88490Maury
88100Cuvelier
88470Maurin
.Jouve
88210Aubertin
88650Wagner
88580Beaulieu
88430Baudouin
88520Bérard
88110Frémont
88420Besnard

Toutes​

La fonction bool_and ou son alias every renvoie vrai si toutes les lignes satisfont la condition.

Exercice : Afficher vrai si tous les articles d'une même famille ont tous leur prix supérieur à 10 €

select famille_code, bool_and(prix > 10) as sup_10
from article
group by famille_code
famille_codesup_10
03BANAfalse
03PECHEfalse
03RHUBARBEfalse
03FIGUEtrue
03ORANGEfalse

Au moins un​

La fonction bool_or renvoie vrai si au moins une lignes satisfait la condition.

Exercice : Afficher vrai si au moins un article d'une famille a un prix supérieur à 5 €

select famille_code, bool_or(prix > 5) as sup_5
from article
group by famille_code
famille_codesup_5
03BANAfalse
03PECHEtrue
03RHUBARBEtrue
03FIGUEtrue
03ORANGEfalse

Concaténation en chaine​

STRING_AGG construit une chaine de caractères séparés par un délimiteur

select string_agg(distinct famille_code, ', ')
from article;
>> '02, 02AROM, 02ARTICHAU, 02ASP, 02AUBE, 02BETT, ...'

Concaténation en tableau​

ARRAY_AGG construit une tableau à partir des éléments. Très utilisé lors d'une sérialisation en JSON par exemple.

select array_agg(distinct famille_code)
from article;
>> ['02', '02AROM', '02ARTICHAU', '02ASP', '02AUBE', '02BETT', ...]

Filtre après agrégation​

HAVING est emblable à WHERE, mais utilisé pour filtrer les résultats des fonctions d'agrégation après un GROUP BY.

Quels sont les personnes qui ont exactement 72 tickets ? (Cote et Lebreton)

select a.nom, a.prenom,
count(t.id) as nb_ticket
from adherent a
join ticket t on a.id = t.adherent_id
group by a.id
having count(t.id) = 72;

Avec postgreSQL et Microsoft SQL Server il n'est pas possible d'utiliser l'alias dans la condition having. La clause having intervient en amont du select dans le moteur d'exécution, l'alias n'est pas encore connu. Il faut réécrire la formule.

Rang​

rank, percent_rank et dense_rank calcule le rang de la données.

cume_dist calcule la distribution cumulée.

Ces fonctions sont en réalité des fenêtres analytiques(window) mais peuvent être utilisées pour explorer la distribution.

Agrégats d'intervalles​

postgreSQL support un type particulier que sont les intervalles de valeur(intervalle) en définitissant dans un même champ une borne inférieure et une supérieure.

range_agg fusionne les intervalles tandis que range_intersect_agg retourne l'intersection.