Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как работи DENSE_RANK() в SQL Server

В 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      |
+----------+---------+--------+

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какво е значението на SELECT ... FOR XML PATH(' ),1,1)?

  2. Най-ефективният начин в SQL Server за получаване на дата от дата+час?

  3. Поправете съобщение 529 „Не е позволено изрично преобразуване от тип данни int в xml“ в SQL Server

  4. Промяна на съпоставянето на SQL Server на нечувствително към главни и малки букви?

  5. Как да се справяме с грешки в вложените транзакции на SQL Server