Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Funktionsweise von RANK() in SQL Server

In SQL Server der RANK() Die Funktion gibt den Rang jeder Zeile innerhalb der Partition einer Ergebnismenge zurück. Der Rang einer Zeile ist eins plus die Anzahl der Ränge, die vor der Zeile stehen.

Syntax

Die Syntax lautet wie folgt:

RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )

partition_by_clause es ist optional. Es teilt die von FROM erzeugte Ergebnismenge -Klausel in Partitionen, auf die die Funktion angewendet wird. Wenn nicht angegeben, behandelt die Funktion alle Zeilen der Ergebnismenge der Abfrage als eine einzige Gruppe.

order_by_clause erforderlich. Es bestimmt die Reihenfolge der Daten, bevor die Funktion angewendet wird.

Beachten Sie, dass OVER -Klausel akzeptiert normalerweise eine rows_or_range_clause , aber dieses Argument kann nicht mit RANK() verwendet werden Funktion.

Beispiel 1 – Grundlegende Verwendung

Hier ist ein einfaches Beispiel, das die Verwendung von RANK() zeigt Funktion:

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

Ergebnis:

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

Unser Hauptaugenmerk liegt auf der ArtistId und Rang Säulen. Wir können sehen, dass der Rang jedes Mal steigt, wenn die ArtistId steigt. Das liegt daran, dass ich nach ArtistId bestelle und somit jeder neue Künstler einen neuen Rang erhält.

Wenn wir uns den Rang ansehen Spalte, können wir ziemlich viele Bindungen sehen. Das heißt, einige Zeilen haben denselben Rang. Dies ist zu erwarten, da ich nach ArtistId bestelle und einige ArtistId-Werte in mehr als einer Zeile stehen.

Diese gebundenen Zeilen eignen sich hervorragend, um zu demonstrieren, wie RANK() funktioniert. Wie bereits erwähnt, erhöht es sich um eins plus die Anzahl der Ränge, die davor lagen. Verbundene Zeilen verursachen Lücken in den Ranking-Werten (d. h. sie erhöhen sich nicht immer um 1). Im obigen Beispiel gibt es einige Lücken. Die erste ist, wo es von 1 bis 6 geht. Dann eine andere, wenn es von 7 bis 9 geht, und so weiter.

Wenn Sie diese Lücken nicht möchten, verwenden Sie DENSE_RANK() , die auf die gleiche Weise funktioniert, außer ohne Lücken. Der dichte Rang wird als eins plus die Anzahl der distinct berechnet Rangwerte, die vor dieser Zeile stehen.

Beispiel 2 – Partitionen

Sie können die Ergebnisse auch in Partitionen aufteilen. Wenn Sie dies tun, wird der Rang für jede Partition berechnet (also beginnt er mit jeder neuen Partition von vorne).

Beispiel:

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

Ergebnis:

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

In diesem Fall partitioniere ich nach Genre. Dadurch wird jede Zeile nur mit den anderen Zeilen in derselben Partition verglichen. Jede Partition bewirkt also, dass der Ranking-Wert wieder bei 1 beginnt.

Beispiel 3 – Ein Anzeigerbeispiel

Hier ist ein möglicher Anwendungsfall, um dem Benutzer den Rang anzuzeigen.

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

Ergebnis:

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

Beachten Sie jedoch, dass alle unentschiedenen Ergebnisse zu Lücken in den Ranking-Werten führen.

Folgendes passiert, wenn Lisa plötzlich mit Barts Punktzahl übereinstimmt:

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

Ergebnis:

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

In diesem Fall wird niemand auf Platz 2 eingestuft, da die ersten beiden Spieler auf Platz 1 liegen.

Wie bereits erwähnt, verwenden Sie DENSE_RANK(), wenn Sie Lücken wie diese beseitigen müssen .

Beispiel 4 – Ersetzen von RANK() durch DENSE_RANK()

Hier ist noch einmal dasselbe Beispiel, außer dass ich dieses Mal DENSE_RANK() verwende :

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

Ergebnis:

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