Comparar ROW_NUMBER, RANK y DENSE_RANK
Objetivos
Al terminar podrás elegir una función de ranking según la forma en que quieres tratar empates.
Concepto
ROW_NUMBER() da a cada fila un número distinto. RANK() comparte puesto entre empates y deja un hueco después. DENSE_RANK() comparte puesto, pero no deja huecos.
Las tres son funciones de ventana: el CTE agrupa primero los pagos por mes y luego la ventana asigna una posición a cada fila mensual. El ORDER BY final decide la presentación; para ROW_NUMBER incluye un desempate estable.
Ejemplo
WITH monthly AS (
SELECT
DATE_FORMAT(payment_date, '%Y-%m') AS payment_month,
SUM(amount) AS total_amount
FROM payment
GROUP BY DATE_FORMAT(payment_date, '%Y-%m')
)
SELECT
payment_month,
ROUND(total_amount, 2) AS total_amount,
ROW_NUMBER() OVER (ORDER BY total_amount DESC, payment_month) AS row_number_rank,
RANK() OVER (ORDER BY total_amount DESC) AS rank_with_gaps,
DENSE_RANK() OVER (ORDER BY total_amount DESC) AS dense_rank_value
FROM monthly
ORDER BY total_amount DESC, payment_month;Un empate depende de los valores de los datos. ROW_NUMBER usa el mes como desempate, mientras RANK y DENSE_RANK comparan solo el total.
Práctica guiada
- Cambia el orden a
ASCy observa qué periodo queda primero. - Quita
payment_monthdeROW_NUMBERy explica por qué el orden entre empates puede variar. - Busca dos filas con el mismo total en un conjunto de prueba para observar el hueco de
RANK.
Reto
Asigna una posición única a las tiendas por importe total. Usa una clave estable para resolver empates y explica cuándo preferirías RANK.
Ver respuesta al reto
WITH store_totals AS (
SELECT s.store_id AS staff_primary_store_id,
SUM(p.amount) AS total_amount
FROM sakila.payment AS p
JOIN sakila.staff AS s ON s.staff_id = p.staff_id
GROUP BY s.store_id
)
SELECT staff_primary_store_id, ROUND(total_amount, 2) AS total_amount,
ROW_NUMBER() OVER (ORDER BY total_amount DESC, staff_primary_store_id) AS position,
RANK() OVER (ORDER BY total_amount DESC) AS rank_with_gaps
FROM store_totals
ORDER BY position;El identificador de tienda desempata ROW_NUMBER; RANK es útil cuando se quiere compartir posición y dejar huecos tras empates.
Quiz
Comprobación
Ya eliges cómo numerar empates. La siguiente lección compara un periodo con el anterior y el siguiente.