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 BY — ne 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 (…)
ROW_NUMBER() OVER (PARTITION BY colonna ORDER BY colonna2)Composants :
PARTITION BY— définit les "groupes" (commeGROUP BY, mais les lignes rester séparés);ORDER BYà l'intérieur deOVER(…)— 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
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) :
| Fonction | Postes |
|---|---|
ROW_NUMBER | 1, 2, 3, 4 (toujours unique) |
RANK | 1, 1, 3, 4 (les égalités partagent une position, laisse des "espaces") |
DENSE_RANK | 1, 1, 2, 3 (les égalités partagent une position, sans espaces) |
Exemple : classement des produits par catégorie
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
-- 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
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.
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
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.
Afficher l'indice
ROW_NUMBER est toujours unique dans la partition.
Solution disponible après 3 tentatives