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 > )
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. Observe que o
OVER
cláusula normalmente aceita uma 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 | +----------+---------+--------+