sql >> Base de Datos >  >> RDS >> Database

Similitudes y diferencias entre las funciones RANK, DENSE_RANK y ROW_NUMBER

Las funciones RANK, DENSE_RANK y ROW_NUMBER se utilizan para recuperar un valor entero creciente. Comienzan con un valor basado en la condición impuesta por la cláusula ORDER BY. Todas estas funciones requieren la cláusula ORDER BY para funcionar correctamente. En el caso de datos particionados, el contador de enteros se restablece a 1 para cada partición.

En este artículo, estudiaremos las funciones RANK, DENSE_RANK y ROW_NUMBER en detalle, pero antes de eso, creemos datos ficticios en los que se pueden usar estas funciones a menos que su base de datos esté completamente respaldada.

Preparación de datos ficticios

Ejecute el siguiente script para crear una base de datos llamada ShowRoom y que contenga una tabla llamada Cars (que contiene 15 registros aleatorios de autos):

CREATE Database ShowRoom;
GO
USE ShowRoom;

CREATE TABLE Cars
(
id INT,
name VARCHAR(50) NOT NULL,
company VARCHAR(50) NOT NULL,
power INT NOT NULL
)


USE ShowRoom
INSERT INTO Cars
VALUES
(1, 'Corrolla', 'Toyota', 1800),
(2, 'City', 'Honda', 1500),
(3, 'C200', 'Mercedez', 2000),
(4, 'Vitz', 'Toyota', 1300),
(5, 'Baleno', 'Suzuki', 1500),
(6, 'C500', 'Mercedez', 5000),
(7, '800', 'BMW', 8000),
(8, 'Mustang', 'Ford', 5000),
(9, '208', 'Peugeot', 5400),
(10, 'Prius', 'Toyota', 3200),
(11, 'Atlas', 'Volkswagen', 5000),
(12, '110', 'Bugatti', 8000),
(13, 'Landcruiser', 'Toyota', 3000),
(14, 'Civic', 'Honda', 1800),
(15, 'Accord', 'Honda', 2000)

Función de RANGO

La función RANK se usa para recuperar filas clasificadas en función de la condición de la cláusula ORDER BY. Por ejemplo, si desea encontrar el nombre del automóvil con la tercera potencia más alta, puede usar la función RANK.
Veamos la función RANK en acción:

SELECT name,company, power,
RANK() OVER(ORDER BY power DESC) AS PowerRank
FROM Cars

La secuencia de comandos anterior encuentra y clasifica todos los registros en la tabla Cars y los ordena en orden de poder descendente. La salida se ve así:

La columna PowerRank en la tabla anterior contiene el RANGO de los autos ordenados por orden descendente de su poder. Una cosa interesante acerca de la función RANK es que si hay un empate entre N registros anteriores para el valor en la columna ORDER BY, las funciones RANK saltan las siguientes N-1 posiciones antes de incrementar el contador. Por ejemplo, en el resultado anterior, hay un empate para los valores en la columna de potencia entre la primera y la segunda fila, por lo tanto, la función RANK salta el siguiente registro (2-1 =1) y salta directamente a la tercera fila.
La función RANK se puede utilizar en combinación con la cláusula PARTITION BY. En ese caso, el rango se restablecerá para cada nueva partición. Echa un vistazo a la siguiente secuencia de comandos:

SELECT name,company, power,
RANK() OVER(PARTITION BY company ORDER BY power DESC) AS PowerRank
FROM Cars

En el script anterior, dividimos los resultados por columna de empresa. Ahora, para cada empresa, el RANGO se restablecerá a 1 como se muestra a continuación:

FUNCIÓN DENSO_RANK

La función DENSE_RANK es similar a la función DENSE_RANK, sin embargo, la función DENSE_RANK no omite ningún rango si hay un empate entre los rangos de los registros anteriores. Echa un vistazo a la siguiente secuencia de comandos.

SELECT name,company, power,
RANK() OVER(PARTITION BY company ORDER BY power DESC) AS PowerRank
FROM Cars

Puede ver en el resultado que, a pesar de que hay un empate entre los rangos de las dos primeras filas, el siguiente rango no se omite y se le ha asignado un valor de 2 en lugar de 3. Al igual que con la función RANK, la cláusula PARTITION BY puede también se puede usar con la función DENSE_RANK como se muestra a continuación:

SELECT name,company, power,
DENSE_RANK() OVER(PARTITION BY company ORDER BY power DESC) AS DensePowerRank
FROM Cars

Función ROW_NUMBER

A diferencia de las funciones RANK y DENSE_RANK, la función ROW_NUMBER simplemente devuelve el número de fila de los registros ordenados que comienzan con 1. Por ejemplo, si las funciones RANK y DENSE_RANK de los primeros dos registros en la columna ORDER BY son iguales, a ambos se les asigna 1 como su RANK y DENSE_RANK. Sin embargo, la función ROW_NUMBER asignará los valores 1 y 2 a esas filas sin tener en cuenta que se tienen en cuenta por igual. Ejecute el siguiente script para ver la función ROW_NUMBER en acción.

SELECT name,company, power,
ROW_NUMBER() OVER(ORDER BY power DESC) AS RowRank
FROM Cars

A partir del resultado, puede ver que la función ROW_NUMBER simplemente asigna un nuevo número de fila a cada registro independientemente de su valor.
La cláusula PARTITION BY también se puede usar con la función ROW_NUMBER como se muestra a continuación:

SELECT name, company, power,
ROW_NUMBER() OVER(PARTITION BY company ORDER BY power DESC) AS RowRank
FROM Cars

La salida se ve así:

Similitudes entre las funciones RANK, DENSE_RANK y ROW_NUMBER

Las funciones RANK, DENSE_RANK y ROW_NUMBER tienen las siguientes similitudes:
1- Todas requieren una cláusula order by.
2- Todas devuelven un número entero creciente con un valor base de 1.
3- Cuando se combinan con una cláusula PARTITION BY, todas estas funciones restablecen el valor entero devuelto a 1 como hemos visto.
4- Si no hay valores duplicados en la columna utilizada por la cláusula ORDER BY, estos las funciones devuelven el mismo resultado.
Para ilustrar el último punto, creemos una nueva tabla Car1 en la base de datos de ShowRoom sin valores duplicados en la columna de potencia. Ejecute el siguiente script:

USE ShowRoom;

CREATE TABLE Cars1
(
id INT,
name VARCHAR(50) NOT NULL,
company VARCHAR(50) NOT NULL,
power INT NOT NULL
)


INSERT INTO Cars1
VALUES
(1, 'Corrolla', 'Toyota', 1800),
(2, 'City', 'Honda', 1500),
(3, 'C200', 'Mercedez', 2000),
(4, 'Vitz', 'Toyota', 1300),
(5, 'Baleno', 'Suzuki', 2500),
(6, 'C500', 'Mercedez', 5000),
(7, '800', 'BMW', 8000),
(8, 'Mustang', 'Ford', 4000),
(9, '208', 'Peugeot', 5400),
(10, 'Prius', 'Toyota', 3200)
The cars1 table has no duplicate values. Now let’s execute the RANK, DENSE_RANK and ROW_NUMBER functions on the Cars1 table ORDER BY power column. Execute the following script:
SELECT name,company, power,
RANK() OVER(ORDER BY power DESC) AS [Rank],
DENSE_RANK() OVER(ORDER BY power DESC) AS [Dense Rank],
ROW_NUMBER() OVER(ORDER BY power DESC) AS [Row Number]
FROM Cars1

La salida se ve así:

Puede ver que no hay valores duplicados en la columna de potencia que se usa en la cláusula ORDER BY, por lo tanto, la salida de las funciones RANK, DENSE_RANK y ROW_NUMBER son las mismas.

Diferencia entre las funciones RANK, DENSE_RANK y ROW_NUMBER

La única diferencia entre las funciones RANK, DENSE_RANK y ROW_NUMBER es cuando hay valores duplicados en la columna que se usa en la cláusula ORDER BY.
Si regresa a la tabla Cars en la base de datos de ShowRoom, puede ver que contiene muchos valores duplicados. Intentemos encontrar el RANK, DENSE_RANK y ROW_NUMBER de la tabla Cars1 ordenados por potencia. Ejecute el siguiente script:
SELECCIONE nombre,empresa,poder,

RANK() OVER(ORDER BY power DESC) AS [Rank],
DENSE_RANK() OVER(ORDER BY power DESC) AS [Dense Rank],
ROW_NUMBER() OVER(ORDER BY power DESC) AS [Row Number]
FROM Cars

La salida se ve así:

A partir de la salida, puede ver que la función RANK omite los siguientes N-1 rangos si hay un empate entre los N rangos anteriores. Por otro lado, la función DENSE_RANK no salta rangos si hay un empate entre rangos. Finalmente, la función ROW_NUMBER no tiene que ver con la clasificación. Simplemente devuelve el número de fila de los registros ordenados. Incluso si hay registros duplicados en la columna utilizada en la cláusula ORDER BY, la función ROW_NUMBER no devolverá valores duplicados. En su lugar, seguirá aumentando independientemente de los valores duplicados.

Enlaces útiles:

Para obtener más información sobre las funciones ROW_NUMBER(), RANK() y DENSE_RANK(), lea el fantástico artículo de Ahmad Yaseen:

Métodos para clasificar filas en SQL Server:ROW_NUMBER(), RANK(), DENSE_RANK() y NTILE()