I SQL Server er RANK()
funktion returnerer rangeringen af hver række inden for partitionen af et resultatsæt. Rangeringen af en række er én plus antallet af rækker, der kommer før rækken.
Syntaks
Syntaksen ser sådan ud:
RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )
partition_by_clause er valgfri. Den deler resultatsættet produceret af FROM
klausul i partitioner, som funktionen anvendes på. Hvis det ikke er angivet, behandler funktionen alle rækker i forespørgselsresultatsættet som en enkelt gruppe.
ordre_by_clause er påkrævet. Det bestemmer rækkefølgen af dataene, før funktionen anvendes.
Bemærk, at OVER
klausul accepterer normalt en rows_or_range_clause , men det argument kan ikke bruges med RANK()
funktion.
Eksempel 1 – Grundlæggende brug
Her er et grundlæggende eksempel, der viser brugen af 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 | +-----------+--------------------------+------------+--------+
Vores hovedfokus er ArtistId og Rank kolonner. Vi kan se, at rangeringen stiger, hver gang ArtistId'et stiger. Dette skyldes, at jeg bestiller efter ArtistId, og derfor vil hver ny kunstner få en ny rang.
Når vi ser på Rank kolonne, kan vi se en del bånd. Det vil sige, at en del rækker deler samme rang. Dette kan forventes, fordi jeg bestiller efter ArtistId, og nogle ArtistId-værdier er i mere end én række.
Disse bundne rækker er gode til at demonstrere hvordan RANK()
arbejder. Som nævnt stiger den med én plus antallet af rækker, der kom før den. Sammenbundne rækker forårsager huller i rangeringsværdierne (dvs. de øges ikke altid med 1). I ovenstående eksempel er der en del huller. Den første er, hvor den går fra 1 til 6. Derefter en anden, når den går fra 7 til 9, og så videre.
Hvis du ikke vil have disse huller, skal du bruge DENSE_RANK()
, som fungerer på samme måde undtagen uden huller. Den tætte rangering beregnes som én plus antallet af distinkte rangordne værdier, der kommer før denne række.
Eksempel 2 – Partitioner
Du kan også opdele resultaterne i partitioner. Når du gør dette, beregnes rangeringen mod hver partition (så den starter forfra med hver ny partition).
Eksempel:
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 dette tilfælde opdeler jeg efter genre. Dette medfører, at hver række kun rangeres i forhold til de andre rækker i samme partition. Så hver partition får rangeringsværdien til at starte ved 1 igen.
Eksempel 3 – Et eksempel på resultattavlen
Her er en mulig use case til at vise rangeringen til brugeren.
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 | +----------+---------+--------+
Vær dog opmærksom på, at eventuelle uafgjorte resultater vil resultere i huller i rangeringsværdierne.
Her er, hvad der sker, hvis Lisa pludselig matcher Barts score:
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 dette tilfælde er ingen rangeret som nummer 2, fordi de første to spillere er lige på rang 1.
Som nævnt, hvis du har brug for at fjerne huller som denne, skal du bruge DENSE_RANK()
.
Eksempel 4 – Erstatning af RANK() med DENSE_RANK()
Her er det samme eksempel igen, bortset fra at denne gang bruger jeg 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 | +----------+---------+--------+