
🧪 Envie de pratiquer ? Exécutez les exemples de cet article dans notre SQL Playground gratuit — aucun logiciel à installer.
La fonction RANK en Oracle SQL : classement et analyse de données
La fonction RANK en Oracle SQL est une fonction analytique puissante qui permet d’attribuer un rang à chaque ligne d’un ensemble de résultats, en fonction d’un critère de tri défini. Utilisée dans des contextes métier variés — ressources humaines, finance, e-commerce — la fonction RANK est indispensable pour produire des classements pertinents et fiables directement dans vos requêtes SQL Oracle.
Définition et utilisation de RANK
La fonction RANK est une fonction de fenêtrage analytique (aussi appelée window function) introduite par Oracle pour répondre aux besoins de classement dans les ensembles de données. Elle attribue un rang entier à chaque ligne selon un ordre précis. Sa caractéristique principale : en cas d’égalité, plusieurs lignes peuvent obtenir le même rang, et le rang suivant tient compte du nombre de lignes ex æquo (on parle de « saut de rang »).
Par exemple, si deux employés partagent le rang 3, le prochain rang attribué sera 5 (et non 4). Ce comportement la distingue de DENSE_RANK, qui ne crée pas de saut.
Cas d’usage en entreprise
- Ressources humaines : classer les salariés par salaire au sein d’un département.
- Commercial : identifier les meilleurs vendeurs du mois par région.
- Finance : classer les produits financiers par performance.
- E-commerce : afficher le top des produits les plus vendus par catégorie.
Syntaxe de la fonction RANK
Oracle propose deux modes d’utilisation pour RANK : en tant que fonction analytique (avec la clause OVER) et en tant que fonction agrégée hypothétique. Dans la grande majorité des cas, c’est la forme analytique qui est utilisée.
Forme analytique
RANK() OVER (
[PARTITION BY colonne1, colonne2, ...]
ORDER BY colonne3 [ASC | DESC], ...
)
Explication des paramètres
RANK(): appel de la fonction, sans argument.OVER (...): définit la fenêtre d’analyse sur laquelle la fonction s’applique.PARTITION BY(optionnel) : divise le jeu de résultats en partitions indépendantes. Le classement redémarre à 1 pour chaque partition. Si omis, toute la table est traitée comme une seule partition.ORDER BY(obligatoire) : définit le critère de tri utilisé pour établir le rang. Sans cet élément, la requête est invalide.
Forme agrégée hypothétique
RANK(valeur1, valeur2, ...) WITHIN GROUP (ORDER BY colonne1, colonne2, ...)
Cette forme permet de calculer le rang qu’obtiendrait une valeur hypothétique si elle était insérée dans le groupe. Elle est moins fréquente mais utile pour des simulations.
Exemples pratiques de RANK en Oracle SQL
Exemple 1 — Classement des employés par salaire dans chaque département
Contexte métier : Une DRH souhaite établir un classement des salaires au sein de chaque département pour préparer les revues annuelles de rémunération.
-- Classement des employés par salaire décroissant, par département
SELECT
employee_id,
last_name,
department_id,
salary,
RANK() OVER (
PARTITION BY department_id -- Redémarre le classement pour chaque département
ORDER BY salary DESC -- Les plus hauts salaires en premier
) AS rang_salaire
FROM employees
ORDER BY department_id, rang_salaire;
Résultat attendu (extrait) :
EMPLOYEE_ID LAST_NAME DEPARTMENT_ID SALARY RANG_SALAIRE
----------- ---------- ------------- ------- ------------
101 King 10 10000 1
102 Blake 10 9000 2
103 Clark 10 9000 2
104 Jones 10 7000 4 -- Saut de rang car deux ex æquo au rang 2
On remarque le saut de rang caractéristique de RANK : après deux employés au rang 2, le suivant passe directement au rang 4.
Exemple 2 — Top 3 des produits les plus vendus par catégorie
Contexte métier : Un responsable e-commerce souhaite afficher les 3 articles les plus vendus dans chaque catégorie de produits pour alimenter un tableau de bord de performance.
-- Sélection des 3 meilleurs produits par catégorie selon le chiffre de ventes
SELECT *
FROM (
SELECT
p.product_id,
p.product_name,
p.category_id,
SUM(od.quantity) AS total_vendu,
RANK() OVER (
PARTITION BY p.category_id -- Un classement par catégorie
ORDER BY SUM(od.quantity) DESC -- Les plus vendus d'abord
) AS rang_ventes
FROM products p
JOIN order_details od ON p.product_id = od.product_id
GROUP BY p.product_id, p.product_name, p.category_id
)
WHERE rang_ventes <= 3 -- On garde uniquement le top 3
ORDER BY category_id, rang_ventes;
Ce type de requête imbriquée est très courant en Oracle : la fonction analytique est calculée dans la sous-requête, puis le filtre WHERE est appliqué dans la requête externe, car on ne peut pas filtrer directement sur un alias de fonction analytique.
Erreurs courantes avec RANK
Erreur : utiliser WHERE pour filtrer directement sur le rang
Une erreur fréquente chez les développeurs SQL débutants consiste à filtrer sur le résultat de RANK() directement dans la clause WHERE de la même requête :
-- ❌ Requête incorrecte : ORA-00904 ou résultat inattendu
SELECT
employee_id,
salary,
RANK() OVER (ORDER BY salary DESC) AS rang
FROM employees
WHERE rang <= 5; -- Erreur : l'alias 'rang' n'est pas encore calculé à ce stade
Explication : En SQL Oracle, la clause WHERE est évaluée avant les fonctions analytiques. L’alias rang n’existe donc pas encore lors du filtrage.
Solution : Encapsuler la requête dans une sous-requête (ou utiliser un CTE avec WITH) :
-- ✅ Requête correcte avec sous-requête
SELECT *
FROM (
SELECT
employee_id,
salary,
RANK() OVER (ORDER BY salary DESC) AS rang
FROM employees
)
WHERE rang <= 5;
Résumé
| Point clé | Détail |
|---|---|
| Type de fonction | Analytique (window function) |
| Gestion des ex æquo | Même rang attribué + saut de rang suivant |
| Clause obligatoire | ORDER BY dans OVER() |
| Clause optionnelle | PARTITION BY pour des classements par groupe |
| Différence avec DENSE_RANK | DENSE_RANK ne crée pas de saut de rang |
| Filtrage sur le rang | Toujours via une sous-requête ou un CTE |
| Compatible Oracle | Oui, depuis Oracle 8i |
Deux bonnes pratiques Oracle
- Toujours utiliser PARTITION BY lorsque vos données sont organisées en groupes logiques (département, catégorie, région) : cela évite un classement global non pertinent et améliore les performances sur de grandes tables.
- Préférer les CTEs (
WITH) aux sous-requêtes imbriquées pour filtrer sur le rang : le code est plus lisible, plus maintenable et Oracle les optimise efficacement.
Aller plus loin
Pour approfondir votre maîtrise des fonctions analytiques Oracle, voici trois sujets complémentaires qui vous permettront de progresser :
- La fonction DENSE_RANK en Oracle SQL : comprenez les différences avec
RANKet choisissez la bonne fonction selon votre besoin de classement continu. - La fonction ROW_NUMBER en Oracle SQL : attribuez un numéro de ligne unique à chaque enregistrement, sans égalité possible, idéal pour la pagination de résultats.
- La clause OVER et PARTITION BY en Oracle SQL : maîtrisez le cœur des fonctions analytiques pour créer des analyses de données avancées et performantes.
