Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come funziona RANK() in SQL Server

In SQL Server, il RANK() La funzione restituisce il rango di ogni riga all'interno della partizione di un set di risultati. Il grado di una riga è uno più il numero di gradi che precedono la riga.

Sintassi

La sintassi è questa:

RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )

partizione_per_clausola è facoltativo. Divide il set di risultati prodotto dal FROM clausola in partizioni a cui viene applicata la funzione. Se non specificata, la funzione tratta tutte le righe del set di risultati della query come un unico gruppo.

ordine_per_clausola è obbligatorio. Determina l'ordine dei dati prima dell'applicazione della funzione.

Nota che il OVER normalmente accetta una clausola rows_or_range_clause , ma quell'argomento non può essere utilizzato con RANK() funzione.

Esempio 1 – Utilizzo di base

Ecco un esempio di base che mostra l'utilizzo di RANK() funzione:

SELECT
  AlbumId,
  AlbumName,
  ArtistId,
  RANK() OVER (ORDER BY ArtistId ASC) 'Rank'
FROM Albums;

Risultato:

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

Il nostro obiettivo principale è ArtistId e Classifica colonne. Possiamo vedere che il rango aumenta ogni volta che aumenta ArtistId. Questo perché ordino per ArtistId, quindi ogni nuovo artista otterrà un nuovo grado.

Quando guardiamo il Rank colonna, possiamo vedere parecchi legami. Cioè, alcune righe condividono lo stesso rango. Questo è prevedibile, perché sto ordinando per ArtistId e alcuni valori di ArtistId sono in più di una riga.

Queste righe legate sono ottime per dimostrare come RANK() lavori. Come accennato, aumenta di uno più il numero di gradi precedenti. Le righe abbinate fanno apparire degli spazi vuoti nei valori della classifica (cioè non sempre si incrementano di 1). Nell'esempio sopra, ci sono alcune lacune. Il primo è dove va da 1 a 6. Poi un altro quando va da 7 a 9, e così via.

Se non vuoi queste lacune, usa DENSE_RANK() , che funziona allo stesso modo tranne che senza interruzioni. Il rango denso viene calcolato come uno più il numero di distinti classifica i valori che precedono quella riga.

Esempio 2 – Partizioni

Puoi anche dividere i risultati in partizioni. Quando lo fai, il rango viene calcolato rispetto a ciascuna partizione (quindi ricomincia da capo a ogni nuova partizione).

Esempio:

SELECT
  Genre,
  AlbumName,
  ArtistId,
  RANK() OVER (PARTITION BY Genre ORDER BY ArtistId ASC) 'Rank'
FROM Albums
INNER JOIN Genres 
ON Albums.GenreId = Genres.GenreId;

Risultato:

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

In questo caso partizione per Genere. Ciò fa sì che ogni riga venga classificata solo rispetto alle altre righe nella stessa partizione. Quindi ogni partizione fa ripartire il valore della classifica da 1.

Esempio 3:un esempio di tabellone segnapunti

Ecco un possibile caso d'uso per visualizzare il grado all'utente.

SELECT  
  Player,
  Score,
  RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

Risultato:

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

Tuttavia, tieni presente che qualsiasi risultato in parità comporterà lacune nei valori di classifica.

Ecco cosa succede se Lisa eguaglia improvvisamente il punteggio di Bart:

SELECT  
  Player,
  Score,
  RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

Risultato:

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

In questo caso nessuno è classificato al numero 2, perché i primi due giocatori sono in parità al rango 1.

Come accennato, se devi eliminare lacune come questa, usa DENSE_RANK() .

Esempio 4 – Sostituzione di RANK() con DENSE_RANK()

Ecco di nuovo lo stesso esempio, tranne che questa volta utilizzo DENSE_RANK() :

SELECT  
  Player,
  Score,
  DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

Risultato:

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