V SQL Server, RANK()
Funkce vrací pořadí každého řádku v rámci oddílu sady výsledků. Pořadí řádku je jedna plus počet řádků, které jsou před řádkem.
Syntaxe
Syntaxe vypadá takto:
RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )
partition_by_clause je volitelný. Rozdělí výslednou sadu vytvořenou FROM
klauzule do oddílů, na které je funkce aplikována. Pokud není zadáno, funkce považuje všechny řádky sady výsledků dotazu za jednu skupinu.
order_by_clause je požadováno. Určuje pořadí dat před aplikací funkce.
Všimněte si, že OVER
klauzule normálně přijímá řádky_nebo_rozsah , ale tento argument nelze použít s RANK()
funkce.
Příklad 1 – Základní použití
Zde je základní příklad ukazující použití RANK()
funkce:
SELECT AlbumId, AlbumName, ArtistId, RANK() OVER (ORDER BY ArtistId ASC) 'Rank' FROM Albums;
Výsledek:
+-----------+--------------------------+------------+--------+ | 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 | +-----------+--------------------------+------------+--------+
Naším hlavním zaměřením je ArtistId a Hodnocení sloupců. Můžeme vidět, že hodnost se zvyšuje pokaždé, když se zvýší ArtistId. Je to proto, že objednávám podle ArtistId, a tak každý nový umělec získá novou hodnost.
Když se podíváme na Pořadí sloupce, můžeme vidět poměrně dost vazeb. To znamená, že několik řádků sdílí stejnou hodnost. Dá se to očekávat, protože objednávám podle ArtistId a některé hodnoty ArtistId jsou ve více než jednom řádku.
Tyto svázané řádky jsou skvělé pro demonstraci RANK()
funguje. Jak již bylo zmíněno, zvýší se o jednu plus počet hodností, které byly před ním. Shodné řádky způsobují, že se v hodnotách hodnocení objevují mezery (tj. ne vždy se zvýší o 1). Ve výše uvedeném příkladu je poměrně dost mezer. První je tam, kde jde od 1 do 6. Pak další, když jde od 7 do 9, a tak dále.
Pokud tyto mezery nechcete, použijte DENSE_RANK()
, který funguje stejně, ale bez mezer. Husté pořadí se vypočítá jako jedna plus počet odlišných hodnot, které jsou před tímto řádkem.
Příklad 2 – Oddíly
Výsledky můžete také rozdělit do oddílů. Když to uděláte, hodnocení se vypočítá pro každý oddíl (takže s každým novým oddílem začíná znovu).
Příklad:
SELECT Genre, AlbumName, ArtistId, RANK() OVER (PARTITION BY Genre ORDER BY ArtistId ASC) 'Rank' FROM Albums INNER JOIN Genres ON Albums.GenreId = Genres.GenreId;
Výsledek:
+---------+--------------------------+------------+--------+ | 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 | +---------+--------------------------+------------+--------+
V tomto případě rozděluji podle žánru. To způsobí, že každý řádek bude hodnocen pouze proti ostatním řádkům ve stejném oddílu. Každý oddíl tedy způsobí, že hodnota hodnocení začne znovu na 1.
Příklad 3 – Příklad hodnotící tabulky
Zde je možný případ použití pro zobrazení hodnocení uživateli.
SELECT Player, Score, RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Výsledek:
+----------+---------+--------+ | 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 | +----------+---------+--------+
Mějte však na paměti, že jakékoli nerozhodné výsledky budou mít za následek mezery v hodnotách hodnocení.
Co se stane, když Lisa náhle dosáhne Bartova skóre:
SELECT Player, Score, RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Výsledek:
+----------+---------+--------+ | 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 | +----------+---------+--------+
V tomto případě se nikdo neumístí na 2. místě, protože první dva hráči jsou na 1. místě nerozhodně.
Jak již bylo zmíněno, pokud potřebujete odstranit mezery, jako je tato, použijte DENSE_RANK()
.
Příklad 4 – Nahrazení RANK() za DENSE_RANK()
Zde je znovu stejný příklad, ale tentokrát používám DENSE_RANK()
:
SELECT Player, Score, DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Výsledek:
+----------+---------+--------+ | 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 | +----------+---------+--------+