W SQL Server DENSE_RANK()
funkcja zwraca rangę każdego wiersza w ramach partycji zbioru wyników. Ranga wiersza to jeden plus liczba odrębnych rang, które znajdują się przed wierszem.
Ta funkcja jest podobna do RANK()
, ale bez luk w wartościach rankingu, które mogą wystąpić przy użyciu RANK()
gdy w zestawie wyników istnieją powiązania.
Składnia
Składnia wygląda tak:
DENSE_RANK ( ) OVER ( [] < order_by_clause > )
FROM
klauzuli na przegrody, do których funkcja jest stosowana. Jeśli nie zostanie określony, wszystkie wiersze zestawu wyników zapytania są traktowane jako jedna grupa.
Zauważ, że OVER
klauzula normalnie akceptuje
Przykład 1 – Podstawowe użycie
Oto podstawowy przykład pokazujący użycie DENSE_RANK()
funkcja:
SELECT AlbumId, AlbumName, ArtistId, DENSE_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 | 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 | +-----------+--------------------------+------------+--------+
Spójrz na ArtistId i ranking kolumny. Ranga wzrasta za każdym razem, gdy zwiększa się identyfikator ArtistId. To dlatego, że zamawiam przez ArtistId, więc każdy nowy artysta otrzyma nową rangę.
Pozycja pozostaje taka sama dla każdego wykonawcy, niezależnie od tego, ile wierszy zawiera ten sam ArtistId, ponieważ wyniki są uporządkowane według tej kolumny. Na przykład pięć wierszy zawiera ten sam ArtistId, a zatem zawiera również tę samą rangę. Innymi słowy, wszyscy mają remis na 1. miejscu
W wielu rzędach pozycja jest identyczna z ArtistId, ale to tylko zbieg okoliczności. Tak się składa, że ArtistId to IDENTITY
kolumna, która zaczyna się od 1 i zwiększa się o 1, co jest również tym, co RANK()
robi. Jednak zobaczysz, że nie są one identyczne we wszystkich rzędach. Na przykład ArtistId przeskakuje od 7 do 9, ale pozycja po prostu wzrasta od 7 do 8 i od tego momentu obie kolumny zawierają różne wartości.
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, DENSE_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 | 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 | +---------+--------------------------+------------+--------+
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, DENSE_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 | +----------+---------+--------+
Pamiętaj, że remis nie wpłynie na kolejne rankingi. Innymi słowy, nie będzie żadnych luk w wartości rangi.
Najlepiej wytłumaczyć to na przykładzie:
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 | +----------+---------+--------+
W tym przypadku Lisa i Bart remisują pod numerem 1. Następnie Burns jest pod numerem 2 (mimo że jest trzecią osobą).
Jeśli wolisz, aby Burns był w tym przypadku na 3 miejscu (a Meg na 4 itd.), użyj RANK()
funkcja zamiast.
Przykład 4 – zastąpienie DENSE_RANK() RANK()
Oto znowu ten sam przykład, ale tym razem używam RANK()
:
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 | +----------+---------+--------+