DENSE_RANK y para qué se usa?
DENSE_RANK es una función de ventana que devuelve el rango de cada fila dentro de una partición (grupo), ordenado según la columna o columnas especificadas en la cláusula ORDER BY. Si varias filas tienen el mismo valor en el criterio de orden, comparten el mismo rango, y la siguiente fila tendrá el rango siguiente inmediato (sin saltos).
Se usa en escenarios como:
DENSE_RANK
DENSE_RANK() OVER ( [PARTITION BY column1, column2, ...] ORDER BY column_name [ASC|DESC] )
PARTITION BY: (Opcional) Divide el conjunto de resultados en particiones o grupos, y reinicia la numeración para cada partición.
ORDER BY: Especifica cómo se deben ordenar las filas dentro de cada partición (o del conjunto completo).
RANK, DENSE_RANK y ROW_NUMBER
RANK: Asigna el mismo rango a filas con valores idénticos, pero deja huecos en la numeración para la siguiente fila (por ejemplo, 1, 2, 2, 4).
DENSE_RANK: Asigna el mismo rango a valores iguales, pero no deja huecos en la secuencia de rangos (por ejemplo, 1, 2, 2, 3).
ROW_NUMBER: Asigna un número único a cada fila, sin considerar empates.
DENSE_RANK
Supongamos que tienes una tabla Empleados con las columnas EmpleadoID, Nombre y Salario, y quieres clasificar a los empleados según su salario en orden descendente:
SELECT EmpleadoID, Nombre, Salario,
DENSE_RANK() OVER (ORDER BY Salario DESC) AS RangoSalario
FROM Empleados;
Resultado:
EmpleadoID | Nombre | Salario | RangoSalario
-----------|---------|---------|-------------
1 | Ana | 5000 | 1
3 | Juan | 4500 | 2
4 | Luis | 4500 | 2
5 | Pedro | 3500 | 3
Las filas con el mismo salario (Juan y Luis) reciben el mismo rango (2), y el siguiente rango es 3 (sin saltar números).
Si deseas clasificar a los empleados dentro de cada departamento según sus ventas, utiliza la cláusula PARTITION BY para agrupar por Departamento:
SELECT Departamento, EmpleadoID, Nombre, Ventas,
DENSE_RANK() OVER (PARTITION BY Departamento ORDER BY Ventas DESC) AS RangoVentas
FROM Empleados;
Resultado:
Departamento | EmpleadoID | Nombre | Ventas | RangoVentas
-------------|------------|--------|--------|------------
Ventas | 1 | Ana | 1500 | 1
Ventas | 2 | Luis | 1300 | 2
Ventas | 3 | Juan | 1300 | 2
Soporte | 4 | Pedro | 900 | 1
Soporte | 5 | Marta | 700 | 2
El ranking se reinicia para cada Departamento, calculando los rangos dentro de cada grupo de manera independiente.
Si tienes una tabla Productos con las columnas Categoria, NombreProducto y Ventas, y deseas encontrar los 3 productos más vendidos por categoría:
WITH RankingProductos AS (
SELECT Categoria, NombreProducto, Ventas,
DENSE_RANK() OVER (PARTITION BY Categoria ORDER BY Ventas DESC) AS RangoVentas
FROM Productos
)
SELECT Categoria, NombreProducto, Ventas
FROM RankingProductos
WHERE RangoVentas <= 3;
Resultado:
Categoria | NombreProducto | Ventas
------------|----------------|-------
Electrónica | TV | 2000
Electrónica | Laptop | 1500
Electrónica | Tablet | 1200
Muebles | Sofá | 900
Muebles | Mesa | 800
Muebles | Silla | 700
La consulta devuelve solo los 3 productos con mayor volumen de ventas dentro de cada categoría.
Puedes usar DENSE_RANK para identificar y eliminar duplicados, manteniendo solo la primera aparición de cada conjunto de valores:
WITH Duplicados AS (
SELECT *,
DENSE_RANK() OVER (PARTITION BY Nombre ORDER BY EmpleadoID) AS Rango
FROM Empleados
)
DELETE FROM Duplicados WHERE Rango > 1;
Esto elimina todas las filas que tengan un rango mayor a 1, manteniendo solo la primera fila para cada nombre.
N productos más vendidos en general
Si quieres ver solo los 3 productos más vendidos en todo el conjunto de datos:
SELECT NombreProducto, Ventas,
DENSE_RANK() OVER (ORDER BY Ventas DESC) AS Rango
FROM Productos
WHERE DENSE_RANK() OVER (ORDER BY Ventas DESC) <= 3;
Este ejemplo devuelve los 3 productos más vendidos, independientemente de su categoría.
DENSE_RANK requiere una cláusula ORDER BY dentro de la cláusula OVER para definir cómo se calculan los rangos.
DENSE_RANK puede verse afectado en tablas grandes con muchos grupos o particiones, especialmente si se usa en combinación con muchas columnas en ORDER BY.
DENSE_RANK no deja huecos en la numeración de rangos, lo cual lo diferencia de RANK, que sí lo hace en casos de empate.
Para más información sobre DENSE_RANK, consulta la documentación oficial de Microsoft.
Jorge García
Fullstack developer