sql >> Base de Datos >  >> RDS >> Sqlserver

Cómo funciona DENSE_RANK() en SQL Server

En SQL Server, el DENSE_RANK() La función devuelve el rango de cada fila dentro de la partición de un conjunto de resultados. El rango de una fila es uno más el número de rangos distintos que vienen antes de la fila.

Esta función es similar a RANK() , pero sin las brechas en los valores de clasificación que pueden ocurrir con RANK() cuando existen empates en el conjunto de resultados.

Sintaxis

La sintaxis es así:

DENSE_RANK ( ) OVER ( [  ] < order_by_clause > )

es opcional. Divide el conjunto de resultados producido por FROM cláusula en particiones a las que se aplica la función. Si no se especifica, todas las filas del conjunto de resultados de la consulta se tratan como un solo grupo.

es requerido. Determina el orden en que la función se aplica a las filas de una partición.

Tenga en cuenta que OVER cláusula normalmente acepta una , pero ese argumento no se puede usar con esta función.

Ejemplo 1:uso básico

Aquí hay un ejemplo básico que muestra el uso de DENSE_RANK() función:

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

Mire el ArtistId y Clasificación columnas El rango aumenta cada vez que aumenta el ArtistId. Esto se debe a que estoy ordenando por ArtistId, por lo que cada nuevo artista obtendrá un nuevo rango.

La clasificación sigue siendo la misma con cada artista, independientemente de cuántas filas contengan el mismo ID de artista, porque los resultados están ordenados por esa columna. Por ejemplo, cinco filas contienen el mismo ArtistId y, por lo tanto, también contienen el mismo rango. En otras palabras, todos están empatados en el rango 1.

En muchas filas, el rango es idéntico al ID de artista, pero esto es solo una coincidencia. Da la casualidad de que ArtistId es una IDENTITY columna que comienza en 1 y se incrementa en 1, que también es lo que RANK() hace. Sin embargo, verá que no son idénticos en todas las filas. Por ejemplo, ArtistId salta de 7 a 9, pero la clasificación simplemente aumenta de 7 a 8 y, a partir de ese momento, ambas columnas contienen valores diferentes.

Ejemplo 2:Particiones

También puede dividir los resultados en particiones. Cuando hace esto, el rango se calcula contra cada partición (por lo que comienza de nuevo con cada nueva partición).

Ejemplo:

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

En este caso divido por Género. Esto hace que cada fila solo se clasifique frente a las otras filas en la misma partición. Entonces, cada partición hace que el valor de clasificación comience de nuevo en 1.

Ejemplo 3:un ejemplo de marcador

Aquí hay un posible caso de uso para mostrar el rango al usuario.

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

Tenga en cuenta que cualquier resultado empatado no afectará las clasificaciones posteriores. En otras palabras, no habrá brechas en el valor de clasificación.

Probablemente esto se explique mejor con un ejemplo:

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

En este caso, Lisa y Bart están empatados en el número 1. Luego, Burns ocupa el número 2 (aunque es la tercera persona).

Si prefiere que Burns ocupe el puesto número 3 en este caso (y Meg en el 4, y así sucesivamente), use el RANK() función en su lugar.

Ejemplo 4:reemplazar DENSE_RANK() con RANK()

Aquí está el mismo ejemplo otra vez, excepto que esta vez 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      |
+----------+---------+--------+