I SQL Server er DENSE_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 distinkte rækker, der kommer før rækken.
Denne funktion ligner RANK()
, men uden de huller i rangeringsværdierne, der kan forekomme med RANK()
når der er bånd i resultatsættet.
Syntaks
Syntaksen ser sådan ud:
DENSE_RANK ( ) OVER ( [] < order_by_clause > )
FROM
klausul i partitioner, som funktionen anvendes på. Hvis det ikke er angivet, behandles alle rækker i forespørgselsresultatsættet som en enkelt gruppe.
Bemærk, at OVER
klausul accepterer normalt en
Eksempel 1 – Grundlæggende brug
Her er et grundlæggende eksempel, der viser brugen af DENSE_RANK()
funktion:
SELECT AlbumId, AlbumName, ArtistId, DENSE_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 | 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 | +-----------+--------------------------+------------+--------+
Se på ArtistId og Rank kolonner. Rangeringen stiger hver gang ArtistId øges. Dette skyldes, at jeg bestiller efter ArtistId, og så vil hver ny kunstner få en ny rang.
Rangeringen forbliver den samme for hver kunstner, uanset hvor mange rækker der indeholder det samme ArtistId, fordi resultaterne er sorteret efter den kolonne. For eksempel indeholder fem rækker det samme ArtistId og derfor indeholder de også den samme rang. Med andre ord er de alle uafgjort til rang 1.
I mange rækker er rangeringen tilfældigvis identisk med ArtistId, men dette er kun en tilfældighed. Tilfældigvis er ArtistId en IDENTITY
kolonne, der starter med 1 og stiger med 1, hvilket også er hvad RANK()
gør. Du vil dog se, at de ikke er identiske på alle rækker. For eksempel springer ArtistId fra 7 til 9, men rangeringen stiger simpelthen fra 7 til 8, og fra det tidspunkt indeholder begge kolonner forskellige værdier.
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, DENSE_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 | 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 | +---------+--------------------------+------------+--------+
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, DENSE_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 opmærksom på, at eventuelle uafhængige resultater ikke vil påvirke efterfølgende rækker. Med andre ord vil der ikke være huller i rangværdien.
Dette forklares nok bedst med et eksempel:
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 | +----------+---------+--------+
I dette tilfælde er Lisa og Bart uafgjort på nummer 1. Så kommer Burns ind på nummer 2 (selvom han er den tredje person).
Hvis du foretrækker, at Burns blev rangeret som nummer 3 i dette tilfælde (og Meg på 4, og så videre), skal du bruge RANK()
funktion i stedet for.
Eksempel 4 – Erstatning af DENSE_RANK() med RANK()
Her er det samme eksempel igen, bortset fra at denne gang bruger jeg RANK()
:
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 | +----------+---------+--------+