Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como DENSE_RANK() funciona no SQL Server


No SQL Server, o DENSE_RANK() A função retorna a classificação de cada linha dentro da partição de um conjunto de resultados. A classificação de uma linha é um mais o número de classificações distintas que vêm antes da linha.

Esta função é semelhante a RANK() , mas sem as lacunas nos valores de classificação que podem ocorrer com RANK() quando existem empates no conjunto de resultados.


Sintaxe


A sintaxe fica assim:
DENSE_RANK ( ) OVER ( [  ] < order_by_clause > )

é opcional. Ele divide o conjunto de resultados produzido pelo FROM cláusula em partições às quais a função é aplicada. Se não for especificado, todas as linhas do conjunto de resultados da consulta serão tratadas como um único grupo.

É necessário. Ele determina a ordem na qual a função se aplica às linhas em uma partição.

Observe que o OVER cláusula normalmente aceita uma , mas esse argumento não pode ser usado com esta função.

Exemplo 1 – Uso básico


Aqui está um exemplo básico mostrando o uso do DENSE_RANK() função:
SELECT
  AlbumId,
  AlbumName,
  ArtistId,
  DENSE_RANK() OVER (ORDER BY ArtistId ASC) 'Rank'
FROM Albums;

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

Veja o ArtistId e Classificação colunas. A classificação aumenta cada vez que o ArtistId aumenta. Isso ocorre porque estou solicitando por ArtistId e, portanto, cada novo artista receberá uma nova classificação.

A classificação permanece a mesma com cada artista, independentemente de quantas linhas contenham o mesmo ArtistId, porque os resultados são ordenados por essa coluna. Por exemplo, cinco linhas contêm o mesmo ArtistId e, portanto, também contêm a mesma classificação. Em outras palavras, eles estão todos empatados no rank 1.

Em muitas linhas, a classificação é idêntica ao ArtistId, mas isso é apenas uma coincidência. Acontece que o ArtistId é um IDENTITY coluna que começa em 1 e incrementa em 1, que também é o que RANK() faz. No entanto, você verá que eles não são idênticos em todas as linhas. Por exemplo, o ArtistId pula de 7 para 9, mas a classificação simplesmente aumenta de 7 para 8 e, a partir desse ponto, ambas as colunas contêm valores diferentes.

Exemplo 2 – Partições


Você também pode dividir os resultados em partições. Quando você faz isso, a classificação é calculada em relação a cada partição (assim ela começa novamente com cada nova partição).

Exemplo:
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;

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

Neste caso eu particiono por Gênero. Isso faz com que cada linha seja classificada apenas em relação às outras linhas na mesma partição. Portanto, cada partição faz com que o valor de classificação comece em 1 novamente.

Exemplo 3 – Exemplo de placar


Aqui está um possível caso de uso para exibir a classificação para o usuário.
SELECT  
  Player,
  Score,
  DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

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

Esteja ciente de que quaisquer resultados empatados não afetarão as classificações subsequentes. Em outras palavras, não haverá lacunas no valor da classificação.

Isso provavelmente é melhor explicado com um exemplo:
SELECT  
  Player,
  Score,
  DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

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

Neste caso, Lisa e Bart estão empatados no número 1. Então Burns vem no número 2 (mesmo sendo a terceira pessoa).

Se você preferir que Burns seja o número 3 neste caso (e Meg em 4, e assim por diante), use o RANK() função em vez disso.

Exemplo 4 – Substituindo DENSE_RANK() por RANK()


Aqui está o mesmo exemplo novamente, exceto que desta vez eu uso RANK() :
SELECT  
  Player,
  Score,
  RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

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