sql >> Databasteknik >  >> RDS >> Sqlserver

Hur RANK() fungerar i SQL Server

I SQL Server, RANK() funktion returnerar rangen för varje rad inom partitionen för en resultatuppsättning. Rangen för en rad är ett plus antalet rangord som kommer före raden.

Syntax

Syntaxen ser ut så här:

RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )

partition_by_clause är valfritt. Den delar resultatuppsättningen som produceras av FROM sats i partitioner som funktionen tillämpas på. Om det inte anges, behandlar funktionen alla rader i frågeresultatuppsättningen som en enda grupp.

order_efter_klausul krävs. Den bestämmer ordningen på data innan funktionen tillämpas.

Observera att OVER sats accepterar normalt en rader_eller_omfångssats , men det argumentet kan inte användas med RANK() funktion.

Exempel 1 – Grundläggande användning

Här är ett grundläggande exempel som visar användningen av RANK() funktion:

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

Resultat:

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

Vårt huvudfokus är ArtistId och Rank kolumner. Vi kan se att rankningen ökar varje gång ArtistId ökar. Detta beror på att jag beställer efter ArtistId, så varje ny artist kommer att få en ny rang.

När vi tittar på Rank kolumn kan vi se en hel del band. Det vill säga, ganska många rader delar samma rang. Detta är att vänta, eftersom jag beställer efter ArtistId och vissa ArtistId-värden finns på mer än en rad.

Dessa bundna rader är bra för att visa hur RANK() Arbetar. Som nämnts ökar den med ett plus antalet grader som kom före den. Kopplade rader gör att luckor visas i rankningsvärdena (dvs. de ökar inte alltid med 1). I exemplet ovan finns det en hel del luckor. Den första är där den går från 1 till 6. Sedan en annan när den går från 7 till 9, och så vidare.

Om du inte vill ha dessa luckor, använd DENSE_RANK() , som fungerar på samma sätt förutom utan luckor. Den täta rangen beräknas som ett plus antalet distinkt rangordna värden som kommer före den raden.

Exempel 2 – Partitioner

Du kan också dela upp resultaten i partitioner. När du gör detta beräknas rankningen mot varje partition (så den börjar om igen med varje ny partition).

Exempel:

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

Resultat:

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

I det här fallet partitionerar jag efter genre. Detta gör att varje rad endast rankas mot de andra raderna i samma partition. Så varje partition gör att rankningsvärdet börjar på 1 igen.

Exempel 3 – Ett exempel på resultattavla

Här är ett möjligt användningsfall för att visa rankningen för användaren.

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

Resultat:

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

Var dock uppmärksam på att eventuella oavgjorda resultat kommer att resultera i luckor i rankningsvärdena.

Så här händer om Lisa plötsligt matchar Barts poäng:

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

Resultat:

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

I det här fallet är ingen rankad som nummer 2, eftersom de två första spelarna är oavgjorda på rang 1.

Som nämnts, om du behöver eliminera luckor som denna, använd DENSE_RANK() .

Exempel 4 – Ersätter RANK() med DENSE_RANK()

Här är samma exempel igen, förutom den här gången använder jag DENSE_RANK() :

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

Resultat:

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

  1. Hur man ansluter en databas med en Amazon VPC

  2. Hur ställer du in autocommit i en SQL Server-session?

  3. Hur kan jag använda mysqli_fetch_array() två gånger?

  4. Katastrofåterställningsalternativ för PostgreSQL distribueras till ett hybridmoln