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

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

В SQL Server, RANK() функцията връща ранга на всеки ред в рамките на дяла на набор от резултати. Рангът на ред е едно плюс броя на ранговете, които идват преди реда.

Синтаксис

Синтаксисът е така:

RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )

раздел_по_клауза е по избор. Той разделя резултатния набор, произведен от FROM клауза в дялове, към които се прилага функцията. Ако не е посочено, функцията третира всички редове от набора от резултати от заявката като една група.

клауза_по_порядък изисква се. Той определя реда на данните преди прилагането на функцията.

Имайте предвид, че OVER клаузата обикновено приема клауза_rows_or_range_clause , но този аргумент не може да се използва с RANK() функция.

Пример 1 – Основна употреба

Ето основен пример, показващ използването на RANK() функция:

SELECT
  AlbumId,
  AlbumName,
  ArtistId,
  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          | 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     |
+-----------+--------------------------+------------+--------+

Основният ни фокус е ArtistId и Ранг колони. Можем да видим, че рангът се увеличава всеки път, когато ArtistId се увеличава. Това е така, защото поръчвам по ArtistId и така всеки нов изпълнител ще получи нов ранг.

Когато погледнем Ранг колона, можем да видим доста връзки. Тоест, доста редове споделят един и същи ранг. Това може да се очаква, защото поръчвам по ArtistId и някои стойности на ArtistId са в повече от един ред.

Тези обвързани редове са чудесни за демонстриране как RANK() върши работа. Както споменахме, той се увеличава с едно плюс броя на ранговете, които са дошли преди него. Свързаните редове причиняват появата на пропуски в стойностите на класирането (т.е. те не винаги се увеличават с 1). В горния пример има доста пропуски. Първият е мястото, където преминава от 1 до 6. След това още едно, когато преминава от 7 до 9, и така нататък.

Ако не искате тези пропуски, използвайте DENSE_RANK() , който работи по същия начин, освен без пропуски. Плътният ранг се изчислява като едно плюс броя на отличителните ранг стойности, които идват преди този ред.

Пример 2 – Дялове

Можете също да разделите резултатите на дялове. Когато направите това, рангът се изчислява спрямо всеки дял (така че започва отново с всеки нов дял).

Пример:

SELECT
  Genre,
  AlbumName,
  ArtistId,
  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          | 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      |
+---------+--------------------------+------------+--------+

В този случай разделя по Жанр. Това кара всеки ред да се класира само спрямо другите редове в същия дял. Така че всеки дял кара стойността на класирането да започне отново от 1.

Пример 3 – Пример за табло

Ето възможен случай на използване за показване на ранга на потребителя.

SELECT  
  Player,
  Score,
  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,
  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      |
+----------+---------+--------+

В този случай никой не се класира на номер 2, тъй като първите двама играчи са изравнени на ранг 1.

Както споменахме, ако трябва да премахнете пропуски като тази, използвайте DENSE_RANK() .

Пример 4 – Замяна на RANK() с DENSE_RANK()

Ето отново същия пример, освен че този път използвам DENSE_RANK() :

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ограничение на клаузата IN в Sql Server

  2. SQL Server:Полезни съвети за начинаещи

  3. 6 проблемни заявки, които значително забавят вашата база данни

  4. Как да получите отделен списък с думи, използвани във всички полеви записи, използвайки MS SQL?

  5. T-SQL - Вмъкване на данни в родителски и дъщерни таблици