SQL analítico · guía rápida

RANK y DENSE_RANK

Las dos funciones asignan posiciones respetando empates. La diferencia está en la posición que aparece después de un empate.

Lectura: 6–8 minEjemplo paso a pasoPráctica con pistas
Contenido de esta guía

La diferencia en una frase

RANK deja huecos después de un empate; DENSE_RANK continúa con la posición siguiente sin huecos. Ambas asignan la misma posición a filas que son iguales según el ORDER BY de la ventana.

Qué pregunta responde cada una

Utiliza RANK cuando la posición debe reflejar cuántas filas aparecen antes. En una competición, dos personas empatadas en primer lugar pueden ir seguidas por el tercer puesto.

Utiliza DENSE_RANK cuando quieres numerar niveles o grupos de valores distintos. Después de dos filas en el nivel 1, el siguiente valor distinto ocupa el nivel 2.

No existe una opción universalmente mejor: la elección depende del significado de la clasificación.

Sintaxis

Estructura
RANK() OVER (ORDER BY columna DESC)

DENSE_RANK() OVER (ORDER BY columna DESC)

Para obtener una clasificación con significado, define un ORDER BY dentro de OVER. SQL Server lo exige sintácticamente; PostgreSQL y SQLite permiten omitirlo, pero entonces el orden no queda definido para una clasificación útil. En SQLite, sin ORDER BY, todas las filas se consideran pares y tanto RANK como DENSE_RANK devuelven 1. Si no quieres romper los empates, no añadas una columna única como id dentro del orden de la ventana.

Ejemplo guiado con empates

Pedidos seleccionados
idtotal
108249.0
111249.0
114203.9
104179.0
118179.0
SQL
SELECT id,
       total,
       RANK() OVER (ORDER BY total DESC) AS posicion_rank,
       DENSE_RANK() OVER (ORDER BY total DESC) AS posicion_densa
FROM pedidos
WHERE id IN (104, 108, 111, 114, 118)
ORDER BY total DESC, id;
Resultado
idtotalposicion_rankposicion_densa
108249.011
111249.011
114203.932
104179.043
118179.043

Por qué aparecen 1, 1, 3

  1. Los dos pedidos de 249 empatan en la primera posición.
  2. RANK cuenta que ya existen dos filas antes del total 203,9 y asigna la posición 3.
  3. DENSE_RANK cuenta valores distintos y asigna el nivel 2.
  4. Los pedidos de 179 vuelven a empatar.

Diferencia con ROW_NUMBER

ROW_NUMBER asigna un número diferente a cada fila, incluso cuando los valores empatan. Para obtener un orden estable con ROW_NUMBER suele añadirse un criterio de desempate. Con RANK y DENSE_RANK, ese criterio cambiaría qué filas se consideran empatadas.

Error frecuente

Eliminar los empates sin querer

Orden que cambia el significado
RANK() OVER (ORDER BY total DESC, id)

Como el id es distinto en cada fila, ya no existen filas iguales según el orden completo. La función asignará posiciones diferentes. Utiliza el id solo en el ORDER BY exterior si quieres una presentación estable sin cambiar el empate.

Comprueba lo aprendido

Básica · apoyo gradual

Clasifica salarios por departamento

Devuelve nombre, departamento, salario y una columna nivel_salarial. Usa DENSE_RANK para clasificar de mayor a menor salario dentro de cada departamento.

Compatibilidad

RANK y DENSE_RANK están disponibles en los motores modernos que soportan funciones de ventana. La definición de “pares” o filas empatadas depende de las expresiones del ORDER BY de la ventana.

Qué debes recordar

  • RANK deja huecos después de los empates.
  • DENSE_RANK no deja huecos.
  • ROW_NUMBER asigna un número único a cada fila.
  • El orden de la ventana decide qué filas empatan.

Conceptos relacionados

Fuentes técnicas consultadas

Se utilizaron para comprobar las definiciones y el tratamiento de empates. La explicación y los ejemplos son originales.