Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak działa RANK() w SQL Server

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

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MS Access wywołanie procedury składowanej SQL Server

  2. Jak przekonwertować listę rozdzielaną przecinkami na wiersze w SQL Server

  3. Lokalne i globalne tabele tymczasowe w SQL Server

  4. Wprowadzenie do synonimów w SQL Server

  5. Czy kolejność kolumn w klauzuli WHERE ma znaczenie?