In SQL Server is de RANK()
functie retourneert de rangorde van elke rij binnen de partitie van een resultaatset. De rangorde van een rij is één plus het aantal rangen dat voor de rij komt.
Syntaxis
De syntaxis gaat als volgt:
RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )
partition_by_clause is optioneel. Het verdeelt de resultatenset geproduceerd door de FROM
clausule in partities waarop de functie wordt toegepast. Indien niet opgegeven, behandelt de functie alle rijen van de queryresultatenset als één groep.
order_by_clause Is benodigd. Het bepaalt de volgorde van de gegevens voordat de functie wordt toegepast.
Merk op dat de OVER
clausule accepteert normaal gesproken een rows_or_range_clause , maar dat argument kan niet worden gebruikt met de RANK()
functie.
Voorbeeld 1 – Basisgebruik
Hier is een eenvoudig voorbeeld dat het gebruik van de RANK()
. laat zien functie:
SELECT AlbumId, AlbumName, ArtistId, 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 | 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 | +-----------+--------------------------+------------+--------+
Onze belangrijkste focus is de ArtistId en Rang kolommen. We kunnen zien dat de rangorde elke keer dat de ArtistId toeneemt, toeneemt. Dit komt omdat ik bestel op ArtistId, en dus krijgt elke nieuwe artiest een nieuwe rang.
Als we kijken naar de Rank kolom zien we nogal wat verbanden. Dat wil zeggen, nogal wat rijen delen dezelfde rangorde. Dit is te verwachten, omdat ik bestel op ArtistId en sommige ArtistId-waarden in meer dan één rij staan.
Deze gebonden rijen zijn geweldig om te laten zien hoe RANK()
werken. Zoals vermeld, wordt het verhoogd met één plus het aantal rangen dat ervoor kwam. Gebonden rijen veroorzaken hiaten in de rangschikkingswaarden (d.w.z. ze worden niet altijd met 1) verhoogd. In bovenstaand voorbeeld zijn er nogal wat hiaten. De eerste is waar het van 1 naar 6 gaat. Dan nog een wanneer het van 7 naar 9 gaat, enzovoort.
Als u deze hiaten niet wilt, gebruikt u DENSE_RANK()
, die op dezelfde manier werkt, behalve zonder gaten. De dichte rangorde wordt berekend als één plus het aantal verschillende rangschik waarden die voor die rij komen.
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, 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 | 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 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, 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 echter rekening mee dat gelijklopende resultaten resulteren in hiaten in de rangschikkingswaarden.
Dit is wat er gebeurt als Lisa plotseling overeenkomt met de score van Bart:
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 | +----------+---------+--------+
In dit geval staat niemand op nummer 2, omdat de eerste twee spelers gelijk staan op rang 1.
Zoals gezegd, als u hiaten zoals deze wilt wegwerken, gebruikt u DENSE_RANK()
.
Voorbeeld 4 – RANK() vervangen door DENSE_RANK()
Hier is hetzelfde voorbeeld opnieuw, maar deze keer gebruik ik DENSE_RANK()
:
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 | +----------+---------+--------+