Passer au contenu principal
eLearner.app
Module 7 · Leçon 2 sur 426/57 dans le cours~14 min
Leçons du module (2/4)

Fonctions de fenêtre : classements et calculs par groupe

Une fonction de fenêtre est une fonction qui opère sur un "groupe de lignes" (la fenêtre) mais — contrairement à GROUP BYne réduit pas le nombre de rows : une valeur calculée sur la fenêtre est attachée à chaque ligne du résultat final.

C'est le bon outil pour les classements, la numérotation progressive, les pourcentages sur un total de groupe, et bien d'autres opérations délicates ou impossible avec GROUP BY.

La syntaxe : function() OVER (…)

SQL
ROW_NUMBER() OVER (PARTITION BY colonna ORDER BY colonna2)

Composants :

  • PARTITION BY — définit les "groupes" (comme GROUP BY, mais les lignes rester séparés);
  • ORDER BY à l'intérieur de OVER(…) — définit l'ordre dans le partition.

OVER () (parenthèses vides) signifie « la table entière comme une seule fenêtre ». Utile pour les calculs comme « pourcentage du total ».

Fonctions de classement

SQL
ROW_NUMBER() OVER (PARTITION BY p ORDER BY o)
RANK()       OVER (PARTITION BY p ORDER BY o)
DENSE_RANK() OVER (PARTITION BY p ORDER BY o)

Différences (avec les valeurs 100, 100, 90, 80) :

FonctionPostes
ROW_NUMBER1, 2, 3, 4 (toujours unique)
RANK1, 1, 3, 4 (les égalités partagent une position, laisse des "espaces")
DENSE_RANK1, 1, 2, 3 (les égalités partagent une position, sans espaces)

Exemple : classement des produits par catégorie

SQL
SELECT name,
       category_id,
       price,
       RANK() OVER (PARTITION BY category_id ORDER BY price DESC) AS rank
FROM   products
ORDER BY category_id, rank;

Pour chaque category_id le RANK repart de 1 et commande par décroissant prix : vous obtenez le classement des produits au sein de chaque catégorie, en une seule tir.

Numérotation progressive

SQL
-- Progressive order number for each customer:
SELECT id,
       customer_id,
       ordered_at,
       ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY ordered_at) AS row_num
FROM   orders
ORDER BY customer_id, row_num;

La première commande de chaque client aura le row_num = 1, la seconde le 2, etc.

Essayez-le

Exercice#sql.m7.l2.e1
Tentatives : 0Chargement…

Pour chaque produit, affichez le nom, l'identifiant de la catégorie, le prix et le classement (le classement par prix décroissant DANS la catégorie ; utilisez RANK). Triez par id de catégorie croissant et par rang croissant.

Chargement de l'éditeur…
Afficher l'indice

PARTITION BYcategory_id groupes, ORDER BY price DESC commandes au sein du groupe.

Solution disponible après 3 tentatives

Exercice de révision

Exercice#sql.m7.l2.e2
Tentatives : 0Chargement…

Pour chaque commande, affichez l'identifiant, le customer_id, la commande_at et le numéro_ligne (ROW_NUMBER progressif par client, classé par ordre croissant). Commandez par customer_id et row_num.

Chargement de l'éditeur…
Afficher l'indice

ROW_NUMBER est toujours unique dans la partition.

Solution disponible après 3 tentatives