Imagínate que curras de camarero (o de barista, si eres más de café) en un restaurante grande. Cada día haces el recuento de las propinas que has ganado. Pero hay un detalle: el restaurante está dividido en zonas, y te interesa saber cuántas propinas se han ganado en cada zona por separado. PARTITION BY es lo que SQL usa para "dividir el restaurante en zonas".
Más formalmente, PARTITION BY se usa en funciones de ventana para dividir todas las filas de una tabla en grupos separados (o "particiones"). Dentro de cada grupo, la función de ventana se ejecuta de nuevo. Es como si aplicaras la función por separado en cada "zona".
Ejemplo: cómo funciona
Supón que tenemos una tabla sales con datos de ventas:
| región | vendedor | cantidad |
|---|---|---|
| North | Alice | 100 |
| North | Bob | 200 |
| South | Alice | 150 |
| South | Charlie | 250 |
Si queremos calcular cuánto dinero ha ganado cada vendedor, pero por separado para cada región, PARTITION BY es justo lo que necesitamos.
Sintaxis de PARTITION BY
La sintaxis es bastante sencilla:
función_de_ventana() OVER (PARTITION BY columna_o_columnas)
función_de_ventana()— por ejemplo,SUM(),AVG(),ROW_NUMBER()y así.PARTITION BY columna— indica por qué columna quieres dividir las filas.OVER()— es el operador que le dice a SQL: "Haz esto dentro de la ventana indicada".
Ejemplo: suma por grupos
Vamos a calcular la suma de ventas para cada región:
SELECT
región,
vendedor,
cantidad,
SUM(cantidad) OVER (PARTITION BY región) AS total_ventas_por_región
FROM sales;
El resultado será así:
| región | vendedor | cantidad | total_ventas_por_región |
|---|---|---|---|
| North | Alice | 100 | 300 |
| North | Bob | 200 | 300 |
| South | Alice | 150 | 400 |
| South | Charlie | 250 | 400 |
¿Qué pasa aquí? SQL divide las filas en grupos según el valor de la columna región (North y South), y luego aplica la función SUM() por separado para cada grupo. Como resultado, las filas dentro del grupo "North" tienen el mismo valor de suma, y las de "South" otro.
Ejemplos de uso de PARTITION BY
Vamos a ver cómo PARTITION BY puede ser útil en situaciones reales.
Ejemplo 1: Ranking dentro de un grupo
Supón que quieres rankear a los vendedores dentro de cada región según la cantidad de ventas. Para eso puedes usar una combinación de PARTITION BY y la función RANK():
SELECT
región,
vendedor,
cantidad,
RANK() OVER (PARTITION BY región ORDER BY cantidad DESC) AS ranking_en_región
FROM sales;
Resultado:
| región | vendedor | cantidad | ranking_en_región |
|---|---|---|---|
| North | Bob | 200 | 1 |
| North | Alice | 100 | 2 |
| South | Charlie | 250 | 1 |
| South | Alice | 150 | 2 |
La función RANK() asigna un ranking dentro de cada grupo región, empezando por 1. Fíjate que para cada grupo los rankings empiezan desde uno.
Ejemplo 2: Comparar cada valor con la media del grupo
Supón que quieres ver cuánto ha ganado cada vendedor en comparación con la media de su región. Usamos AVG():
SELECT
región,
vendedor,
cantidad,
AVG(cantidad) OVER (PARTITION BY región) AS media_ventas_por_región,
cantidad - AVG(cantidad) OVER (PARTITION BY región) AS diferencia_con_media
FROM sales;
Resultado:
| región | vendedor | cantidad | media_ventas_por_región | diferencia_con_media |
|---|---|---|---|---|
| North | Alice | 100 | 150 | -50 |
| North | Bob | 200 | 150 | 50 |
| South | Alice | 150 | 200 | -50 |
| South | Charlie | 250 | 200 | 50 |
Primero, SQL divide las filas en grupos por región. Luego calcula el valor medio AVG(cantidad) para cada grupo. Por último, para cada fila calcula la diferencia entre su valor y la media.
Ejemplo 3: Numerar filas dentro de un grupo
Digamos que quieres numerar todas las transacciones dentro de cada grupo de región. Usamos ROW_NUMBER():
SELECT
región,
vendedor,
cantidad,
ROW_NUMBER() OVER (PARTITION BY región ORDER BY cantidad DESC) AS número_fila
FROM sales;
Resultado:
| región | vendedor | cantidad | número_fila |
|---|---|---|---|
| North | Bob | 200 | 1 |
| North | Alice | 100 | 2 |
| South | Charlie | 250 | 1 |
| South | Alice | 150 | 2 |
Comparación con GROUP BY
A menudo hay confusión entre PARTITION BY y GROUP BY. Vamos a compararlos:
GROUP BY
GROUP BY cambia la estructura del resultado — convierte las filas de la tabla en agregados. Por ejemplo:
SELECT
región,
SUM(cantidad) AS total_ventas
FROM sales
GROUP BY región;
Resultado:
| región | total_ventas |
|---|---|
| North | 300 |
| South | 400 |
Aquí perdemos la info de los vendedores, porque los datos se agregan.
PARTITION BY
PARTITION BY, en cambio, no cambia la estructura. Seguimos viendo cada fila, pero tenemos valores extra calculados por grupos. O sea, PARTITION BY permite agregar sin perder detalles.
Errores comunes usando PARTITION BY
Error 1: Olvidar PARTITION BY
A veces quieres agrupar datos, pero se te olvida usar PARTITION BY. Por ejemplo:
SELECT
región,
vendedor,
cantidad,
SUM(cantidad) OVER () AS total_ventas
FROM sales;
Resultado:
| región | vendedor | cantidad | total_ventas |
|---|---|---|---|
| North | Alice | 100 | 700 |
| North | Bob | 200 | 700 |
| South | Alice | 150 | 700 |
| South | Charlie | 250 | 700 |
Aquí SUM(cantidad) se calcula para toda la tabla, no por cada región. Si quieres tener en cuenta las regiones, no te olvides de poner PARTITION BY región.
Error 2: Orden incorrecto en ORDER BY
El orden de las filas dentro de la ventana es importante para funciones como RANK() o ROW_NUMBER(). Ten cuidado cuando uses ORDER BY dentro de OVER().
GO TO FULL VERSION