Contenido de esta guía
Respuesta rápida
GROUPING SETS permite calcular varios niveles de agrupación en una sola consulta. ROLLUP genera niveles jerárquicos y CUBE genera todas las combinaciones de las dimensiones indicadas.
SELECT region, canal, SUM(importe) AS ventas
FROM ventas
GROUP BY GROUPING SETS (
(region, canal),
(region),
()
);El conjunto vacío () representa el total general.
Tres herramientas, tres intenciones
| Forma | Qué calcula | Uso típico |
|---|---|---|
GROUPING SETS | Solo los grupos que enumeras | Informe con niveles concretos |
ROLLUP(a,b) | (a,b), (a), () | Jerarquías y subtotales |
CUBE(a,b) | (a,b), (a), (b), () | Análisis multidimensional |
Ejemplo: detalle, subtotal por región y total
Con cuatro ventas de prueba —Norte/Web 120, Norte/Tienda 80, Sur/Web 150 y Sur/Tienda 50— el patrón produce seis filas: cuatro combinaciones, dos subtotales regionales y un total general.
SELECT region, canal, SUM(importe) AS ventas
FROM ventas
GROUP BY ROLLUP (region, canal);En PostgreSQL y SQL Server, este ROLLUP equivale a GROUPING SETS ((region, canal), (region), ()). MySQL 8.4 también documenta ROLLUP, aunque su soporte de modificadores no es idéntico al de PostgreSQL/SQL Server.
Por qué GROUPING() importa cuando hay NULL
Los motores representan con NULL las columnas que no participan en una fila de subtotal. Pero una columna de datos también puede contener un NULL real. GROUPING(columna) permite distinguir ambas situaciones en los motores que lo soportan.
SELECT
CASE WHEN GROUPING(region) = 1 THEN 'TOTAL' ELSE region END AS region,
SUM(importe) AS ventas
FROM ventas
GROUP BY ROLLUP (region);No uses simplemente COALESCE(region, 'TOTAL') si un NULL real en region tiene significado propio: mezclarías datos ausentes con una fila de resumen.
Compatibilidad entre motores
- PostgreSQL: soporta
GROUPING SETS,ROLLUPyCUBE. - SQL Server: soporta las tres formas en
GROUP BY. - MySQL 8.4: documenta
ROLLUPyGROUPING(); para combinaciones arbitrarias que no cubre su sintaxis, una alternativa explícita esUNION ALL. - SQLite: no ofrece estos modificadores en su
GROUP BY; puedes expresar los niveles necesarios con varias agregaciones unidas medianteUNION ALL.
SELECT region, canal, SUM(importe) AS ventas
FROM ventas
GROUP BY region, canal
UNION ALL
SELECT region, NULL, SUM(importe)
FROM ventas
GROUP BY region
UNION ALL
SELECT NULL, NULL, SUM(importe)
FROM ventas;Esta alternativa es más larga, pero hace explícitos los niveles y permite verificar el resultado en motores sin GROUPING SETS.
Práctica: total por región + total general
Elige solo dos niveles
Con la tabla ventas(region, canal, importe), devuelve un subtotal por region y una fila de total general, sin detalle por canal.
region.().Solución razonada
SELECT region, SUM(importe) AS ventas
FROM ventas
GROUP BY GROUPING SETS ((region), ());El resultado esperado es Norte = 200, Sur = 200 y una fila total = 400. SQLite 3.46.1 no ejecuta la sintaxis GROUPING SETS; el resultado se comprobó localmente con la forma equivalente basada en UNION ALL.
Qué debes recordar
- GROUPING SETS calcula exactamente los niveles que enumeras.
- ROLLUP recorre prefijos jerárquicos; CUBE genera todas las combinaciones.
- GROUPING() distingue NULL de datos frente a NULL de subtotal.
- La compatibilidad varía: no copies la sintaxis entre motores sin comprobarla.