Las funciones de ventana (Window Functions) son una de las herramientas más potentes del lenguaje SQL.
Permiten realizar cálculos y análisis avanzados sobre conjuntos de filas sin agrupar los resultados, a diferencia de las funciones tradicionales como SUM() o AVG() con GROUP BY.
Con las funciones de ventana puedes:
- Asignar números de fila (
ROW_NUMBER()) - Calcular rangos (
RANK(),DENSE_RANK()) - Obtener promedios móviles
- Comparar una fila con la anterior o siguiente (
LAG(),LEAD())
Y lo mejor: todo sin perder detalle en tus resultados.
¿Qué es una función de ventana?
Una función de ventana realiza un cálculo sobre un conjunto de filas relacionadas con la fila actual, definido por la cláusula OVER().
Su sintaxis básica es:
función_ventana() OVER (
PARTITION BY columna1
ORDER BY columna2
) PARTITION BYdivide los datos en grupos (similares aGROUP BY).ORDER BYdefine el orden en el que se aplicará el cálculo dentro de cada grupo.
Ejemplo 1: Numerar filas con ROW_NUMBER()
Supongamos la tabla empleados que ya usamos en temas anteriores:
| id_empleado | nombre | puesto | salario | id_departamento |
|---|---|---|---|---|
| 1 | Ana Torres | Gerente de Ventas | 90000 | 1 |
| 2 | Luis Pérez | Ejecutivo de Ventas | 65000 | 1 |
| 3 | Marta Díaz | Especialista Marketing | 72000 | 2 |
| 4 | Pedro García | Desarrollador Backend | 80000 | 4 |
| 5 | Sofía Ruiz | Desarrollador Frontend | 80000 | 4 |
Podemos numerar a los empleados por salario dentro de cada departamento:
SELECT
nombre,
id_departamento,
salario,
ROW_NUMBER() OVER (
PARTITION BY id_departamento
ORDER BY salario DESC
) AS posicion
FROM empleados;
📘 Resultado:
Cada empleado obtiene una posición según su salario dentro de su propio departamento.
Ejemplo 2: Calcular rangos con RANK() y DENSE_RANK()
Ambas funciones asignan posiciones, pero con ligeras diferencias:
SELECT
nombre,
id_departamento,
salario,
RANK() OVER (ORDER BY salario DESC) AS rango,
DENSE_RANK() OVER (ORDER BY salario DESC) AS rango_denso
FROM empleados;
📘 Diferencia clave:
RANK()salta posiciones en caso de empate (por ejemplo, 1, 2, 2, 4).DENSE_RANK()no deja huecos (1, 2, 2, 3).
Ejemplo 3: Comparar una fila con la anterior (LAG()) o siguiente (LEAD())
Estas funciones son ideales para detectar cambios entre periodos o valores consecutivos:
SELECT
nombre,
salario,
LAG(salario) OVER (ORDER BY salario DESC) AS salario_anterior,
LEAD(salario) OVER (ORDER BY salario DESC) AS salario_siguiente
FROM empleados; 📘 Resultado:
Puedes ver cuánto gana el empleado anterior o siguiente según el orden de salario.
Ejemplo 4: Promedio móvil con AVG() y OVER()
SELECT
nombre,
salario,
AVG(salario) OVER (ORDER BY salario ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS promedio_movil
FROM empleados; Esto calcula el promedio de cada fila junto con la anterior y la siguiente.
Diferencias entre motores SQL
| Motor | Soporte de funciones de ventana | Notas |
|---|---|---|
| SQL Server | ✅ Completo | Desde versiones 2012+ |
| PostgreSQL | ✅ Completo | Incluye funciones avanzadas (LAG, LEAD, NTILE) |
| MySQL | ✅ Desde versión 8.0 | Limitado en versiones anteriores |
| SQLite | ✅ Desde versión 3.25 | Ideal para aprendizaje |
Buenas prácticas
✅ Usa PARTITION BY solo cuando realmente necesites separar grupos.
✅ Evita ordenar por columnas sin índices si trabajas con grandes volúmenes.
✅ Combina las funciones de ventana con CTE para crear reportes complejos.
Conclusión
Las funciones de ventana te permiten analizar información fila por fila sin perder el detalle completo del conjunto de datos.
Son esenciales para análisis financieros, reportes de desempeño, y comparaciones dinámicas.
Practica en línea
Puedes ver y ejecutar todos estos ejemplos en 👉 db-fiddle.com