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

Fonctionnement de DENSE_RANK() dans SQL Server

Dans SQL Server, le DENSE_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 distincts qui précèdent la ligne.

Cette fonction est similaire à RANK() , mais sans les écarts dans les valeurs de classement qui peuvent se produire avec RANK() lorsqu'il existe des égalités dans le jeu de résultats.

Syntaxe

La syntaxe ressemble à ceci :

DENSE_RANK ( ) OVER ( [  ] < order_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é, toutes les lignes du jeu de résultats de la requête sont traitées comme un seul groupe.

est requis. Il détermine l'ordre dans lequel la fonction s'applique aux lignes d'une partition.

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

Exemple 1 - Utilisation de base

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

SELECT
  AlbumId,
  AlbumName,
  ArtistId,
  DENSE_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          | 2      |
| 19        | All Night Wrong          | 3          | 3      |
| 20        | The Sixteen Men of Tain  | 3          | 3      |
| 12        | Big Swing Face           | 4          | 4      |
| 4         | Ziltoid the Omniscient   | 5          | 5      |
| 5         | Casualties of Cool       | 5          | 5      |
| 6         | Epicloud                 | 5          | 5      |
| 3         | Singing Down the Lane    | 6          | 6      |
| 16        | Long Lost Suitcase       | 7          | 7      |
| 17        | Praise and Blame         | 7          | 7      |
| 18        | Along Came Jones         | 7          | 7      |
| 11        | No Sound Without Silence | 9          | 8      |
| 21        | Yo Wassup                | 9          | 8      |
| 22        | Busted                   | 9          | 8      |
| 13        | Blue Night               | 12         | 9      |
| 14        | Eternity                 | 12         | 9      |
| 15        | Scandinavia              | 12         | 9      |
+-----------+--------------------------+------------+--------+

Regardez l' ArtistId et Rang Colonnes. Le rang augmente chaque fois que l'ArtistId augmente. C'est parce que je commande par ArtistId, et donc chaque nouvel artiste obtiendra un nouveau rang.

Le classement reste le même pour chaque artiste, quel que soit le nombre de lignes contenant le même ArtistId, car les résultats sont triés par cette colonne. Par exemple, cinq lignes contiennent le même ArtistId et donc elles contiennent également le même rang. En d'autres termes, ils sont tous à égalité pour le rang 1.

Dans de nombreuses lignes, le rang est identique à l'ArtistId, mais ce n'est qu'une coïncidence. Il se trouve que l'ArtistId est un IDENTITY colonne qui commence à 1 et incrémente de 1, ce qui est aussi ce que RANK() Est-ce que. Cependant, vous verrez qu'ils ne sont pas identiques sur toutes les lignes. Par exemple, l'ArtistId passe de 7 à 9, mais le classement passe simplement de 7 à 8, et à partir de ce moment, les deux colonnes contiennent des valeurs différentes.

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,
  DENSE_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          | 2      |
| Pop     | Long Lost Suitcase       | 7          | 1      |
| Pop     | Praise and Blame         | 7          | 1      |
| Pop     | Along Came Jones         | 7          | 1      |
| Pop     | No Sound Without Silence | 9          | 2      |
| Pop     | Blue Night               | 12         | 3      |
| Pop     | Eternity                 | 12         | 3      |
| Pop     | Scandinavia              | 12         | 3      |
| 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          | 2      |
| Rock    | Ziltoid the Omniscient   | 5          | 3      |
| Rock    | Casualties of Cool       | 5          | 3      |
| Rock    | Epicloud                 | 5          | 3      |
+---------+--------------------------+------------+--------+

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,
  DENSE_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      |
+----------+---------+--------+

N'oubliez pas que les résultats à égalité n'affecteront pas les rangs suivants. En d'autres termes, il n'y aura pas d'écart dans la valeur du classement.

Ceci est probablement mieux expliqué avec un exemple :

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      |
+----------+---------+--------+

Dans ce cas, Lisa et Bart sont à égalité au numéro 1. Ensuite, Burns arrive au numéro 2 (même s'il est la troisième personne).

Si vous préférez que Burns soit classé numéro 3 dans ce cas (et Meg à 4, et ainsi de suite), utilisez le RANK() fonction à la place.

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

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

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      |
+----------+---------+--------+