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

Comment RANK() fonctionne dans SQL Server

Dans SQL Server, le RANK() La fonction renvoie le rang de chaque ligne dans la partition d'un ensemble de résultats. Le rang d'une ligne est un plus le nombre de rangs qui précèdent la ligne.

Syntaxe

La syntaxe ressemble à ceci :

RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )

partition_by_clause est facultatif. Il divise le jeu de résultats produit par le FROM clause en partitions auxquelles la fonction est appliquée. S'il n'est pas spécifié, la fonction traite toutes les lignes du jeu de résultats de la requête comme un seul groupe.

clause_order_by est requis. Il détermine l'ordre des données avant l'application de la fonction.

Notez que le OVER la clause accepte normalement une rows_or_range_clause , mais cet argument ne peut pas être utilisé avec le RANK() fonction.

Exemple 1 - Utilisation de base

Voici un exemple de base montrant l'utilisation du RANK() fonction :

SELECT
  AlbumId,
  AlbumName,
  ArtistId,
  RANK() OVER (ORDER BY ArtistId ASC) 'Rank'
FROM Albums;

Résultat :

+-----------+--------------------------+------------+--------+
| AlbumId   | AlbumName                | ArtistId   | Rank   |
|-----------+--------------------------+------------+--------|
| 1         | Powerslave               | 1          | 1      |
| 7         | Somewhere in Time        | 1          | 1      |
| 8         | Piece of Mind            | 1          | 1      |
| 9         | Killers                  | 1          | 1      |
| 10        | No Prayer for the Dying  | 1          | 1      |
| 2         | Powerage                 | 2          | 6      |
| 19        | All Night Wrong          | 3          | 7      |
| 20        | The Sixteen Men of Tain  | 3          | 7      |
| 12        | Big Swing Face           | 4          | 9      |
| 4         | Ziltoid the Omniscient   | 5          | 10     |
| 5         | Casualties of Cool       | 5          | 10     |
| 6         | Epicloud                 | 5          | 10     |
| 3         | Singing Down the Lane    | 6          | 13     |
| 16        | Long Lost Suitcase       | 7          | 14     |
| 17        | Praise and Blame         | 7          | 14     |
| 18        | Along Came Jones         | 7          | 14     |
| 11        | No Sound Without Silence | 9          | 17     |
| 21        | Yo Wassup                | 9          | 17     |
| 22        | Busted                   | 9          | 17     |
| 13        | Blue Night               | 12         | 20     |
| 14        | Eternity                 | 12         | 20     |
| 15        | Scandinavia              | 12         | 20     |
+-----------+--------------------------+------------+--------+

Notre objectif principal est l' ArtistId et Rang Colonnes. Nous pouvons voir que le rang augmente chaque fois que l'ArtistId augmente. C'est parce que je commande par ArtistId, et donc chaque nouvel artiste recevra un nouveau classement.

Quand on regarde le Rang colonne, nous pouvons voir pas mal de liens. C'est-à-dire que plusieurs lignes partagent le même rang. C'est à prévoir, car je commande par ArtistId et certaines valeurs ArtistId sont dans plus d'une ligne.

Ces lignes liées sont idéales pour montrer comment RANK() œuvres. Comme mentionné, il s'incrémente de un plus le nombre de rangs qui l'ont précédé. Les lignes liées entraînent l'apparition d'écarts dans les valeurs de classement (c'est-à-dire qu'elles n'incrémentent pas toujours de 1). Dans l'exemple ci-dessus, il y a pas mal de lacunes. Le premier est là où ça va de 1 à 6. Puis un autre quand ça va de 7 à 9, et ainsi de suite.

Si vous ne voulez pas ces écarts, utilisez DENSE_RANK() , qui fonctionne de la même manière sauf sans espace. Le rang dense est calculé comme un plus le nombre de distincts classer les valeurs qui précèdent cette ligne.

Exemple 2 – Partitions

Vous pouvez également diviser les résultats en partitions. Lorsque vous faites cela, le classement est calculé par rapport à chaque partition (il recommence donc à chaque nouvelle partition).

Exemple :

SELECT
  Genre,
  AlbumName,
  ArtistId,
  RANK() OVER (PARTITION BY Genre ORDER BY ArtistId ASC) 'Rank'
FROM Albums
INNER JOIN Genres 
ON Albums.GenreId = Genres.GenreId;

Résultat :

+---------+--------------------------+------------+--------+
| Genre   | AlbumName                | ArtistId   | Rank   |
|---------+--------------------------+------------+--------|
| Country | Singing Down the Lane    | 6          | 1      |
| Country | Yo Wassup                | 9          | 2      |
| Country | Busted                   | 9          | 2      |
| Jazz    | All Night Wrong          | 3          | 1      |
| Jazz    | The Sixteen Men of Tain  | 3          | 1      |
| Jazz    | Big Swing Face           | 4          | 3      |
| Pop     | Long Lost Suitcase       | 7          | 1      |
| Pop     | Praise and Blame         | 7          | 1      |
| Pop     | Along Came Jones         | 7          | 1      |
| Pop     | No Sound Without Silence | 9          | 4      |
| Pop     | Blue Night               | 12         | 5      |
| Pop     | Eternity                 | 12         | 5      |
| Pop     | Scandinavia              | 12         | 5      |
| Rock    | Powerslave               | 1          | 1      |
| Rock    | Somewhere in Time        | 1          | 1      |
| Rock    | Piece of Mind            | 1          | 1      |
| Rock    | Killers                  | 1          | 1      |
| Rock    | No Prayer for the Dying  | 1          | 1      |
| Rock    | Powerage                 | 2          | 6      |
| Rock    | Ziltoid the Omniscient   | 5          | 7      |
| Rock    | Casualties of Cool       | 5          | 7      |
| Rock    | Epicloud                 | 5          | 7      |
+---------+--------------------------+------------+--------+

Dans ce cas, je partitionne par Genre. Ainsi, chaque ligne n'est classée que par rapport aux autres lignes de la même partition. Ainsi, chaque partition fait recommencer la valeur de classement à 1.

Exemple 3 - Un exemple de tableau de bord

Voici un cas d'utilisation possible pour afficher le classement à l'utilisateur.

SELECT  
  Player,
  Score,
  RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

Résultat :

+----------+---------+--------+
| Player   | Score   | Rank   |
|----------+---------+--------|
| Bart     | 2010    | 1      |
| Burns    | 1270    | 2      |
| Meg      | 1030    | 3      |
| Marge    | 990     | 4      |
| Lisa     | 710     | 5      |
| Ned      | 666     | 6      |
| Apu      | 350     | 7      |
| Homer    | 1       | 8      |
+----------+---------+--------+

Cependant, n'oubliez pas que tout résultat à égalité entraînera des écarts dans les valeurs de classement.

Voici ce qui se passe si Lisa correspond soudainement au score de Bart :

SELECT  
  Player,
  Score,
  RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

Résultat :

+----------+---------+--------+
| Player   | Score   | Rank   |
|----------+---------+--------|
| Lisa     | 2010    | 1      |
| Bart     | 2010    | 1      |
| Burns    | 1270    | 3      |
| Meg      | 1030    | 4      |
| Marge    | 990     | 5      |
| Ned      | 666     | 6      |
| Apu      | 350     | 7      |
| Homer    | 1       | 8      |
+----------+---------+--------+

Dans ce cas, personne n'est classé numéro 2, car les deux premiers joueurs sont à égalité au rang 1.

Comme mentionné, si vous avez besoin d'éliminer des lacunes telles que celle-ci, utilisez DENSE_RANK() .

Exemple 4 - Remplacement de RANK() par DENSE_RANK()

Voici à nouveau le même exemple, sauf que cette fois j'utilise DENSE_RANK() :

SELECT  
  Player,
  Score,
  DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

Résultat :

+----------+---------+--------+
| Player   | Score   | Rank   |
|----------+---------+--------|
| Lisa     | 2010    | 1      |
| Bart     | 2010    | 1      |
| Burns    | 1270    | 2      |
| Meg      | 1030    | 3      |
| Marge    | 990     | 4      |
| Ned      | 666     | 5      |
| Apu      | 350     | 6      |
| Homer    | 1       | 7      |
+----------+---------+--------+