In SQL Server, de DENSE_RANK()
functie retourneert de rangorde van elke rij binnen de partitie van een resultaatset. De rangorde van een rij is één plus het aantal verschillende rangen dat voor de rij komt.
Deze functie is vergelijkbaar met RANK()
, maar zonder de hiaten in de rangschikkingswaarden die kunnen optreden met RANK()
wanneer er verbanden zijn in de resultaatset.
Syntaxis
De syntaxis gaat als volgt:
DENSE_RANK ( ) OVER ( [] < order_by_clause > )
FROM
clausule in partities waarop de functie wordt toegepast. Indien niet opgegeven, worden alle rijen van de queryresultatenset als één groep behandeld.
Merk op dat de OVER
clausule accepteert normaal gesproken een
Voorbeeld 1 – Basisgebruik
Hier is een eenvoudig voorbeeld van het gebruik van de DENSE_RANK()
functie:
SELECT AlbumId, AlbumName, ArtistId, DENSE_RANK() OVER (ORDER BY ArtistId ASC) 'Rank' FROM Albums;
Resultaat:
+-----------+--------------------------+------------+--------+ | 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 | +-----------+--------------------------+------------+--------+
Kijk naar de ArtistId en Rang kolommen. Elke keer dat de ArtistId stijgt, wordt de rangorde verhoogd. Dit komt omdat ik bestel op ArtistId, en dus krijgt elke nieuwe artiest een nieuwe rang.
De rangorde blijft bij elke artiest hetzelfde, ongeacht hoeveel rijen dezelfde ArtistId bevatten, omdat de resultaten op die kolom zijn geordend. Zo bevatten vijf rijen dezelfde ArtistId en dus ook dezelfde rangorde. Met andere woorden, ze staan allemaal op gelijke hoogte voor rang 1.
In veel rijen is de rangorde identiek aan de ArtistId, maar dit is gewoon toeval. Toevallig is de ArtistId een IDENTITY
kolom die begint bij 1 en wordt verhoogd met 1, wat ook is wat RANK()
. is doet. U zult echter zien dat ze niet in alle rijen identiek zijn. De ArtistId springt bijvoorbeeld van 7 naar 9, maar de rangorde wordt gewoon verhoogd van 7 naar 8, en vanaf dat moment bevatten beide kolommen verschillende waarden.
Voorbeeld 2 – Partities
U kunt de resultaten ook in partities verdelen. Wanneer je dit doet, wordt de rangorde berekend voor elke partitie (dus begint het opnieuw met elke nieuwe partitie).
Voorbeeld:
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;
Resultaat:
+---------+--------------------------+------------+--------+ | 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 | +---------+--------------------------+------------+--------+
In dit geval verdeel ik op genre. Dit zorgt ervoor dat elke rij alleen wordt gerangschikt tegen de andere rijen in dezelfde partitie. Dus elke partitie zorgt ervoor dat de rangordewaarde weer bij 1 begint.
Voorbeeld 3 – Een voorbeeld van een scorebord
Hier is een mogelijke use-case voor het weergeven van de rang aan de gebruiker.
SELECT Player, Score, DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Resultaat:
+----------+---------+--------+ | 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 | +----------+---------+--------+
Houd er rekening mee dat gelijklopende resultaten de volgende rangen niet beïnvloeden. Met andere woorden, er zullen geen gaten in de rangorde zijn.
Dit kan waarschijnlijk het beste worden uitgelegd met een voorbeeld:
SELECT Player, Score, DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Resultaat:
+----------+---------+--------+ | 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 | +----------+---------+--------+
In dit geval staan Lisa en Bart gelijk op nummer 1. Dan komt Burns binnen op nummer 2 (ook al is hij de derde persoon).
Als je liever hebt dat Burns in dit geval op nummer 3 stond (en Meg op 4, enzovoort), gebruik dan de RANK()
in plaats daarvan functioneren.
Voorbeeld 4 – DENSE_RANK() vervangen door RANK()
Hier is hetzelfde voorbeeld opnieuw, maar deze keer gebruik ik RANK()
:
SELECT Player, Score, RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Resultaat:
+----------+---------+--------+ | 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 | +----------+---------+--------+