В SQL Server, DENSE_RANK()
функцията връща ранга на всеки ред в рамките на дяла на набор от резултати. Рангът на ред е един плюс броят на отделните рангове, които идват преди реда.
Тази функция е подобна на RANK()
, но без пропуските в стойностите за класиране, които могат да възникнат с RANK()
когато има връзки в набора от резултати.
Синтаксис
Синтаксисът е така:
DENSE_RANK ( ) OVER ( [] < order_by_clause > )
FROM
клауза в дялове, към които се прилага функцията. Ако не е посочено, всички редове от набора от резултати от заявката се третират като една група.
Имайте предвид, че OVER
клаузата обикновено приема
Пример 1 – Основна употреба
Ето основен пример, показващ използването на DENSE_RANK()
функция:
SELECT AlbumId, AlbumName, ArtistId, DENSE_RANK() OVER (ORDER BY ArtistId ASC) 'Rank' FROM Albums;
Резултат:
+-----------+--------------------------+------------+--------+ | 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 | +-----------+--------------------------+------------+--------+
Вижте Идентификатор на изпълнител и Ранг колони. Рангът се увеличава всеки път, когато ArtistId се увеличава. Това е така, защото поръчвам от ArtistId и така всеки нов изпълнител ще получи нов ранг.
Рангът остава същият за всеки изпълнител, независимо колко реда съдържат същия ArtistId, тъй като резултатите са подредени по тази колона. Например пет реда съдържат един и същ ArtistId и следователно те също съдържат същия ранг. С други думи, всички те са изравнени за ранг 1.
В много редове рангът е идентичен с ArtistId, но това е просто съвпадение. Случва се, че ArtistId е IDENTITY
колона, която започва от 1 и се увеличава с 1, което също е това, което RANK()
прави. Въпреки това ще видите, че те не са еднакви на всички редове. Например ArtistId прескача от 7 на 9, но рангът просто се увеличава от 7 на 8 и от този момент нататък и двете колони съдържат различни стойности.
Пример 2 – Дялове
Можете също да разделите резултатите на дялове. Когато направите това, рангът се изчислява спрямо всеки дял (така че започва отново с всеки нов дял).
Пример:
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;
Резултат:
+---------+--------------------------+------------+--------+ | 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 | +---------+--------------------------+------------+--------+
В този случай разделя по Жанр. Това кара всеки ред да се класира само спрямо другите редове в същия дял. Така че всеки дял кара стойността на класирането да започне отново от 1.
Пример 3 – Пример за табло
Ето възможен случай на използване за показване на ранга на потребителя.
SELECT Player, Score, DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Резултат:
+----------+---------+--------+ | 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 | +----------+---------+--------+
Имайте предвид, че нито един равен резултат няма да повлияе на следващите рангове. С други думи, няма да има пропуски в стойността на ранга.
Това вероятно е най-добре обяснено с пример:
SELECT Player, Score, DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Резултат:
+----------+---------+--------+ | 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 | +----------+---------+--------+
В този случай Лиза и Барт са изравнени под номер 1. Тогава Бърнс идва под номер 2 (въпреки че той е третото лице).
Ако предпочитате Бърнс да е класиран номер 3 в този случай (и Мег на 4 и така нататък), използвайте RANK()
функция вместо това.
Пример 4 – Замяна на DENSE_RANK() с RANK()
Ето отново същия пример, освен че този път използвам RANK()
:
SELECT Player, Score, RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Резултат:
+----------+---------+--------+ | 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 | +----------+---------+--------+