queryLab · software_de_entrenamiento en espera
Nivel 4 · Avanzado · SQL · avanzado

[SQL 14] Funciones de ventana

ROW_NUMBER, RANK, DENSE_RANK, NTILE, LAG, LEAD, acumulados y porcentajes con OVER.
0 / 7 retos resueltos 📘 Mapa de SQL de las clases 10 y 11 · WINDOW FUNCTIONS · SQL COMANDOS (PARTITION BY)
Al terminar esta práctica podrás…
  • Calcular rankings por grupo con ROW_NUMBER, RANK, DENSE_RANK y PARTITION BY.
  • Comparar cada fila con la anterior o la siguiente con LAG y LEAD.
  • Obtener acumulados, promedios por grupo y porcentajes sin perder el detalle.
  • Resolver el clásico «top-N por grupo» combinando una ventana con una CTE.

Las funciones de ventana calculan un valor para cada fila mirando un conjunto de filas relacionadas (la «ventana»), pero sin colapsarlas como hace GROUP BY: el resultado conserva todas las filas y agrega una columna calculada.

La ventana se define con OVER (PARTITION BY … ORDER BY …):

  • PARTITION BY divide en grupos (por ejemplo, por departamento); el cálculo se reinicia en cada uno.
  • ORDER BY define el orden dentro de la ventana (para rankings, LAG/LEAD y acumulados).
  • Sin PARTITION BY, la ventana es toda la tabla.

Las funciones de agregación también se pueden usar como ventana: AVG(salary) OVER (PARTITION BY department_id) devuelve el promedio del departamento en cada fila.

Las funciones de ventana se calculan después del WHERE y del GROUP BY: para filtrar por su resultado (por ejemplo «puesto ≤ 3») se envuelven en una CTE o subconsulta.

Sintaxis
SELECT col,
       ROW_NUMBER() OVER (PARTITION BY grupo ORDER BY col DESC) AS rn,
       SUM(col)     OVER (ORDER BY fecha)                     AS acumulado,
       LAG(col)     OVER (ORDER BY fecha)                     AS anterior
FROM tabla;
ROW_NUMBER
Correlativo único 1, 2, 3… (en empate decide el orden).
RANK / DENSE_RANK
Empates comparten puesto; RANK deja huecos (1,1,3), DENSE_RANK no (1,1,2).
NTILE(n)
Reparte las filas en n grupos parejos (cuartiles, deciles).
LAG / LEAD
Valor de la fila anterior / siguiente según el ORDER BY.
SUM() OVER (ORDER BY)
Total acumulado (running total).
AVG() OVER (PARTITION BY)
El promedio del grupo repetido en cada fila.
SQLite 3.25+ / MySQL 8+ / Oracle / PostgreSQL
Misma sintaxis OVER (PARTITION BY … ORDER BY …)

1 · Ejemplos guiados · ejecuta y modifica cada bloque

01Ranking dentro de cada departamento
Compara las tres funciones de ranking: observa los empates.
sql-window.sql
Presiona «ejecutar» para ver el resultado.
02Top 3 por departamento
La ventana se calcula en una CTE y luego se filtra por el puesto.
sql-window.sql
Presiona «ejecutar» para ver el resultado.
03Promedio del grupo y diferencia
Cada fila conserva su detalle y además ve el promedio de su departamento.
sql-window.sql
Presiona «ejecutar» para ver el resultado.
04Total acumulado
La planilla acumulada a medida que se fue contratando gente.
sql-window.sql
Presiona «ejecutar» para ver el resultado.
05Porcentaje del total del grupo
Qué parte de la planilla de su departamento representa cada salario.
sql-window.sql
Presiona «ejecutar» para ver el resultado.
06LAG y LEAD
Días transcurridos desde la contratación anterior, y quién fue contratado después.
sql-window.sql
Presiona «ejecutar» para ver el resultado.
07Cuartiles con NTILE
Repartimos a los empleados en 4 grupos parejos según su salario y resumimos cada cuartil.
sql-window.sql
Presiona «ejecutar» para ver el resultado.

⚠ Errores frecuentes

  • Filtrar por la ventana en el WHERE (WHERE RANK() OVER (…) <= 3): no se puede; usa una CTE o subconsulta.
  • Usar ROW_NUMBER con empates sin desempate: el resultado puede variar entre ejecuciones. Agrega una columna única al ORDER BY.
  • Confundir PARTITION BY (grupos dentro de la ventana) con GROUP BY (colapsa filas).
  • Olvidar el ORDER BY dentro del OVER en un acumulado: sin él, SUM() OVER () da el total en todas las filas.

2 · Retos con corrección automática

Escribe tu solución y pulsa comprobar (Ctrl + Enter). Tu consulta y la solución se ejecutan en bases limpias y se comparan los resultados: no importan los nombres de las columnas, sí los datos (y el orden, cuando el reto lo pide). Si te atascas, usa la pista o mira el resultado esperado.

3 · Preguntas tipo solemne

1. Salarios 9000, 9000, 8000. ¿Qué devuelve RANK() ordenando de mayor a menor?
2. ¿Qué diferencia hay entre GROUP BY department_id y OVER (PARTITION BY department_id)?
3. ¿Qué función trae el valor de la fila anterior?