PARTITION BY EN MYSQL: CÓMO FUNCIONA Y EJEMPLOS
Desde MySQL 8.0 las funciones de ventana revolucionaron las consultas analíticas. Y el corazón de casi todas es PARTITION BY: divide el conjunto de resultados en particiones (grupos) y hace que la función se calcule de forma independiente en cada grupo. Se diferencia de "GROUP BY" porque agrupa y reduce filas (pierdes detalle) y "PARTITION BY" agrupa pero mantiene todas las filas siendo ideal para rankings, acumulados por categoría, comparaciones intra-grupo, etc...Ejemplo:
-- Ventas por departamento y empleado
SELECT
departamento,
empleado,
importe,
fecha,
-- Acumulado reiniciado por departamento
SUM(importe) OVER (
PARTITION BY departamento
ORDER BY fecha
) AS acumulado_depto,
-- Ranking descendente por importe dentro de cada depto
DENSE_RANK() OVER (
PARTITION BY departamento
ORDER BY importe DESC
) AS ranking_depto
FROM ventas
ORDER BY departamento, fecha;
- Cada departamento es una partición independiente: El SUM() se reinicia al cambiar de departamento.
- El ranking también se calcula solo dentro de cada departamento.
- Top-N por grupo (ej. top 3 vendedores por región)
SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY region ORDER BY ventas DESC) AS rn FROM leaderboard ) t WHERE rn <= 3; - Comparar con valor anterior (LAG):
SELECT fecha, ventas, ventas - LAG(ventas) OVER (PARTITION BY producto ORDER BY fecha) AS variacion FROM ventas_diarias; - Porcentaje dentro del total del grupo:
SELECT departamento, empleado, importe, importe / SUM(importe) OVER (PARTITION BY departamento) * 100 AS pct_del_depto FROM ventas; - Eliminar duplicados manteniendo el más reciente:
DELETE FROM tabla WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY email ORDER BY created_at DESC) AS rn FROM usuarios ) t WHERE rn > 1 );