W SQL Server RANK()
funkcja zwraca rangę każdego wiersza w ramach partycji zbioru wyników. Ranga wiersza to jeden plus liczba rang poprzedzających ten wiersz.
Składnia
Składnia wygląda tak:
RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )
partition_by_clause jest opcjonalne. Dzieli zestaw wyników utworzony przez FROM
klauzuli na przegrody, do których funkcja jest stosowana. Jeśli nie zostanie określony, funkcja traktuje wszystkie wiersze zestawu wyników zapytania jako pojedynczą grupę.
order_by_clause jest wymagane. Określa kolejność danych przed zastosowaniem funkcji.
Zauważ, że OVER
klauzula normalnie przyjmuje rows_or_range_clause , ale tego argumentu nie można używać z RANK()
funkcja.
Przykład 1 – Podstawowe użycie
Oto podstawowy przykład pokazujący użycie RANK()
funkcja:
SELECT AlbumId, AlbumName, ArtistId, RANK() OVER (ORDER BY ArtistId ASC) 'Rank' FROM Albums;
Wynik:
+-----------+--------------------------+------------+--------+ | 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 | +-----------+--------------------------+------------+--------+
Naszym głównym celem jest ArtistId i ranking kolumny. Widzimy, że ranga wzrasta za każdym razem, gdy zwiększa się ArtistId. Dzieje się tak, ponieważ zamawiam według ArtistId, więc każdy nowy artysta otrzyma nową rangę.
Kiedy patrzymy na ranking kolumna, widzimy sporo więzi. Oznacza to, że sporo wierszy ma tę samą rangę. Należy się tego spodziewać, ponieważ zamawiam według ArtistId, a niektóre wartości ArtistId znajdują się w więcej niż jednym wierszu.
Te powiązane wiersze świetnie nadają się do zademonstrowania, jak RANK()
Pracuje. Jak wspomniano, zwiększa się o jeden plus liczba rang, które pojawiły się przed nim. Związane wiersze powodują pojawienie się luk w wartościach rankingu (tj. nie zawsze zwiększają się o 1). W powyższym przykładzie jest sporo luk. Pierwsza to zmiana z 1 na 6. Kolejna, gdy liczba ta zmienia się z 7 na 9 i tak dalej.
Jeśli nie chcesz tych luk, użyj DENSE_RANK()
, który działa w ten sam sposób, z wyjątkiem przerw. Ranking gęsty jest obliczany jako jeden plus liczba różnych wartości rankingu znajdujące się przed tym wierszem.
Przykład 2 – Partycje
Możesz także podzielić wyniki na partycje. Kiedy to zrobisz, ranga jest obliczana dla każdej partycji (więc zaczyna się od nowa z każdą nową partycją).
Przykład:
SELECT Genre, AlbumName, ArtistId, RANK() OVER (PARTITION BY Genre ORDER BY ArtistId ASC) 'Rank' FROM Albums INNER JOIN Genres ON Albums.GenreId = Genres.GenreId;
Wynik:
+---------+--------------------------+------------+--------+ | 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 | +---------+--------------------------+------------+--------+
W tym przypadku dzielę według gatunku. Powoduje to, że każdy wiersz jest klasyfikowany tylko względem innych wierszy w tej samej partycji. Tak więc każda partycja powoduje, że wartość rankingu ponownie zaczyna się od 1.
Przykład 3 – Przykład tablicy wyników
Oto możliwy przypadek użycia do wyświetlania rangi użytkownikowi.
SELECT Player, Score, RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Wynik:
+----------+---------+--------+ | 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 | +----------+---------+--------+
Należy jednak pamiętać, że wszelkie remisowe wyniki spowodują luki w wartościach rankingu.
Oto, co się stanie, jeśli Lisa nagle dopasuje wynik Barta:
SELECT Player, Score, RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Wynik:
+----------+---------+--------+ | 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 | +----------+---------+--------+
W tym przypadku nikt nie jest na drugim miejscu, ponieważ dwóch pierwszych graczy ma remis na pierwszym miejscu
Jak wspomniano, jeśli chcesz wyeliminować luki, takie jak ta, użyj DENSE_RANK()
.
Przykład 4 – Zastąpienie RANK() DENSE_RANK()
Oto znowu ten sam przykład, ale tym razem używam DENSE_RANK()
:
SELECT Player, Score, DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Wynik:
+----------+---------+--------+ | 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 | +----------+---------+--------+