Database
 sql >> Base de données >  >> RDS >> Database

Similitudes et différences entre les fonctions RANK, DENSE_RANK et ROW_NUMBER

Les fonctions RANK, DENSE_RANK et ROW_NUMBER permettent de récupérer une valeur entière croissante. Ils commencent par une valeur basée sur la condition imposée par la clause ORDER BY. Toutes ces fonctions nécessitent la clause ORDER BY pour fonctionner correctement. En cas de données partitionnées, le compteur d'entiers est réinitialisé à 1 pour chaque partition.

Dans cet article, nous étudierons en détail les fonctions RANK, DENSE_RANK et ROW_NUMBER, mais avant cela, créons des données factices sur lesquelles ces fonctions peuvent être utilisées à moins que votre base de données ne soit entièrement sauvegardée.

Préparation des données factices

Exécutez le script suivant pour créer une base de données appelée ShowRoom et contenant une table appelée Cars (qui contient 15 enregistrements aléatoires de voitures) :

CREATE Database ShowRoom;
GO
USE ShowRoom;

CREATE TABLE Cars
(
id INT,
name VARCHAR(50) NOT NULL,
company VARCHAR(50) NOT NULL,
power INT NOT NULL
)


USE ShowRoom
INSERT INTO Cars
VALUES
(1, 'Corrolla', 'Toyota', 1800),
(2, 'City', 'Honda', 1500),
(3, 'C200', 'Mercedez', 2000),
(4, 'Vitz', 'Toyota', 1300),
(5, 'Baleno', 'Suzuki', 1500),
(6, 'C500', 'Mercedez', 5000),
(7, '800', 'BMW', 8000),
(8, 'Mustang', 'Ford', 5000),
(9, '208', 'Peugeot', 5400),
(10, 'Prius', 'Toyota', 3200),
(11, 'Atlas', 'Volkswagen', 5000),
(12, '110', 'Bugatti', 8000),
(13, 'Landcruiser', 'Toyota', 3000),
(14, 'Civic', 'Honda', 1800),
(15, 'Accord', 'Honda', 2000)

Fonction RANG

La fonction RANK est utilisée pour récupérer des lignes classées en fonction de la condition de la clause ORDER BY. Par exemple, si vous voulez trouver le nom de la voiture avec la troisième puissance la plus élevée, vous pouvez utiliser la fonction RANK.
Voyons la fonction RANK en action :

SELECT name,company, power,
RANK() OVER(ORDER BY power DESC) AS PowerRank
FROM Cars

Le script ci-dessus trouve et classe tous les enregistrements de la table Cars et les classe par ordre décroissant de puissance. La sortie ressemble à ceci :

La colonne PowerRank du tableau ci-dessus contient le RANG des voitures classées par ordre décroissant de leur puissance. Une chose intéressante à propos de la fonction RANK est que s'il y a une égalité entre N enregistrements précédents pour la valeur dans la colonne ORDER BY, les fonctions RANK ignorent les N-1 positions suivantes avant d'incrémenter le compteur. Par exemple, dans le résultat ci-dessus, il y a une égalité pour les valeurs dans la colonne de puissance entre les 1ère et 2ème lignes, donc la fonction RANK saute l'enregistrement suivant (2-1 =1) et saute directement à la 3ème ligne.
La fonction RANK peut être utilisée en combinaison avec la clause PARTITION BY. Dans ce cas, le rang sera réinitialisé pour chaque nouvelle partition. Jetez un oeil au script suivant :

SELECT name,company, power,
RANK() OVER(PARTITION BY company ORDER BY power DESC) AS PowerRank
FROM Cars

Dans le script ci-dessus, nous divisons les résultats par colonne de société. Désormais, pour chaque entreprise, le RANK sera réinitialisé à 1 comme indiqué ci-dessous :

Fonction DENSE_RANK

La fonction DENSE_RANK est similaire à la fonction RANK mais la fonction DENSE_RANK ne saute aucun rang s'il existe une égalité entre les rangs des enregistrements précédents. Jetez un oeil au script suivant.

SELECT name,company, power,
RANK() OVER(PARTITION BY company ORDER BY power DESC) AS PowerRank
FROM Cars

Vous pouvez voir à partir de la sortie que malgré l'existence d'une égalité entre les rangs des deux premières lignes, le rang suivant n'est pas ignoré et a reçu la valeur 2 au lieu de 3. Comme avec la fonction RANK, la clause PARTITION BY peut également être utilisé avec la fonction DENSE_RANK comme indiqué ci-dessous :

SELECT name,company, power,
DENSE_RANK() OVER(PARTITION BY company ORDER BY power DESC) AS DensePowerRank
FROM Cars

Fonction ROW_NUMBER

Contrairement aux fonctions RANK et DENSE_RANK, la fonction ROW_NUMBER renvoie simplement le numéro de ligne des enregistrements triés en commençant par 1. Par exemple, si les fonctions RANK et DENSE_RANK des deux premiers enregistrements de la colonne ORDER BY sont égales, les deux se voient attribuer 1 comme leur RANK et DENSE_RANK. Cependant, la fonction ROW_NUMBER attribuera les valeurs 1 et 2 à ces lignes sans tenir compte du fait qu'elles sont également prises en compte. Exécutez le script suivant pour voir la fonction ROW_NUMBER en action.

SELECT name,company, power,
ROW_NUMBER() OVER(ORDER BY power DESC) AS RowRank
FROM Cars

À partir de la sortie, vous pouvez voir que la fonction ROW_NUMBER attribue simplement un nouveau numéro de ligne à chaque enregistrement, quelle que soit sa valeur.
La clause PARTITION BY peut également être utilisée avec la fonction ROW_NUMBER comme indiqué ci-dessous :

SELECT name, company, power,
ROW_NUMBER() OVER(PARTITION BY company ORDER BY power DESC) AS RowRank
FROM Cars

La sortie ressemble à ceci :

Similarités entre les fonctions RANK, DENSE_RANK et ROW_NUMBER

Les fonctions RANK, DENSE_RANK et ROW_NUMBER présentent les similitudes suivantes :
1- Elles nécessitent toutes une clause order by.
2- Toutes renvoient un entier croissant avec une valeur de base de 1.
3- Lorsqu'elles sont combinées avec une clause PARTITION BY, toutes ces fonctions réinitialisent la valeur entière retournée à 1 comme nous l'avons vu.
4- S'il n'y a pas de valeurs en double dans la colonne utilisée par la clause ORDER BY, ces renvoient la même sortie.
Pour illustrer le dernier point, créons une nouvelle table Car1 dans la base de données ShowRoom sans valeurs en double dans la colonne de puissance. Exécutez le script suivant :

USE ShowRoom;

CREATE TABLE Cars1
(
id INT,
name VARCHAR(50) NOT NULL,
company VARCHAR(50) NOT NULL,
power INT NOT NULL
)


INSERT INTO Cars1
VALUES
(1, 'Corrolla', 'Toyota', 1800),
(2, 'City', 'Honda', 1500),
(3, 'C200', 'Mercedez', 2000),
(4, 'Vitz', 'Toyota', 1300),
(5, 'Baleno', 'Suzuki', 2500),
(6, 'C500', 'Mercedez', 5000),
(7, '800', 'BMW', 8000),
(8, 'Mustang', 'Ford', 4000),
(9, '208', 'Peugeot', 5400),
(10, 'Prius', 'Toyota', 3200)
The cars1 table has no duplicate values. Now let’s execute the RANK, DENSE_RANK and ROW_NUMBER functions on the Cars1 table ORDER BY power column. Execute the following script:
SELECT name,company, power,
RANK() OVER(ORDER BY power DESC) AS [Rank],
DENSE_RANK() OVER(ORDER BY power DESC) AS [Dense Rank],
ROW_NUMBER() OVER(ORDER BY power DESC) AS [Row Number]
FROM Cars1

La sortie ressemble à ceci :

Vous pouvez voir qu'il n'y a pas de valeurs en double dans la colonne de puissance qui est utilisée dans la clause ORDER BY, donc la sortie des fonctions RANK, DENSE_RANK et ROW_NUMBER est la même.

Différence entre les fonctions RANK, DENSE_RANK et ROW_NUMBER

La seule différence entre les fonctions RANK, DENSE_RANK et ROW_NUMBER est lorsqu'il y a des valeurs en double dans la colonne utilisée dans la clause ORDER BY.
Si vous revenez à la table Cars dans la base de données ShowRoom, vous pouvez voir qu'elle contient beaucoup de valeurs en double. Essayons de trouver les RANK, DENSE_RANK et ROW_NUMBER de la table Cars1 triés par puissance. Exécutez le script suivant :
SELECT name,company, power,

RANK() OVER(ORDER BY power DESC) AS [Rank],
DENSE_RANK() OVER(ORDER BY power DESC) AS [Dense Rank],
ROW_NUMBER() OVER(ORDER BY power DESC) AS [Row Number]
FROM Cars

La sortie ressemble à ceci :

À partir de la sortie, vous pouvez voir que la fonction RANK saute les N-1 rangs suivants s'il y a une égalité entre les N rangs précédents. D'autre part, la fonction DENSE_RANK ne saute pas les rangs s'il existe une égalité entre les rangs. Enfin, la fonction ROW_NUMBER n'a aucun souci avec le classement. Il renvoie simplement le numéro de ligne des enregistrements triés. Même s'il existe des enregistrements en double dans la colonne utilisée dans la clause ORDER BY, la fonction ROW_NUMBER ne renverra pas de valeurs en double. Au lieu de cela, il continuera à s'incrémenter quelles que soient les valeurs en double.

Liens utiles :

Pour en savoir plus sur les fonctions ROW_NUMBER(), RANK() et DENSE_RANK(), lisez l'article fantastique d'Ahmad Yaseen :

Méthodes pour classer les lignes dans SQL Server :ROW_NUMBER(), RANK(), DENSE_RANK() et NTILE()