Sei sulla pagina 1di 9

Csar Manivesa http://sql.manivesa.

com

CUBE y ROLLUP del SQL

Cuando tenemos que mostrar informacin de nuestra base de datos a los usuarios habitualmente creamos informes con Visual Basic, con Crystal Reports, con los Analysis Services de Microsoft SQL Server 2000 o con lo que queramos. Con estas herramientas podemos realizar cualquier tipo de clculo sobre los datos almacenados, y especialmente calcular sumas, totales, promedios Pero el lenguaje SQL tambin nos proporciona herramientas para hacer la mayor parte del trabajo en el servidor (ahorrndonos posteriores problemas). Como ya conoceris tenemos clusulas como GROUP BY para agrupar, las funciones de agregado para contar, sumar, promediar y la clusula COMPUTE BY para hacer resmenes. Y si queremos calcular subtotales y totales generales en una misma consulta? Pues tambin existen las clusulas CUBE y ROLLUP que son las que vamos a tratar aqu. Vamos a trabajar con la siguiente tabla por no complicar los ejemplos ni el cdigo SQL. Adems una tabla como esta aunque no sea real sirve perfectamente para mostrar como funciona WITH CUBE. Id TipoTransaccion Divisa ---------------- -------------------------------- -------------------------------------- ----------1 Entrada Euro 2 Entrada Euro 3 Salida Dolar 4 Entrada Libra 5 Salida Dolar 6 Entrada Euro 7 Entrada Dolar 8 Salida Libra 9 Entrada Euro 10 Entrada Libra 11 Entrada Yen 12 Salida Libra 13 Entrada Euro 14 Salida Yen 15 Entrada Libra 16 Entrada Euro 17 Entrada Euro 18 Salida Dolar 19 Entrada Dolar 20 Salida Libra 21 Entrada Euro 22 Entrada Libra 23 Entrada Yen Cantidad 200 1300 2000 500 1000 300 5000 500 700 400 20000 300 4000 30000 3000 400 900 4000 1200 900 2100 200 25000

Introduccin

Qu preguntas solucionamos con CUBE y ROLLUP?

24 25 26

Entrada Entrada Entrada

Libra Euro NULL

400 700 2000

(26 filas afectadas) Es una tabla en la que se guarda informacin sobre transacciones econmicas en las que tenemos tres tipos de datos. Si la transaccin es de entrada o de salida, la moneda en la que se hace y la cantidad. Ahora vamos a empezar a hacer preguntas de tipo OLAP (on-line analytical processing) para analizar los datos que tenemos almacenados. Primera pregunta: Cuntos transacciones tenemos de entrada y de salida? Bueno, para resolver esto podemos escribir una consulta sencilla con un GROUP BY y un COUNT SELECT TipoTransaccion, COUNT(IdTransaccion) FROM Movimientos GROUP BY TipoTransaccion TipoTransaccion -------------------------------------Entrada Salida (2 filas afectadas) Cantidad Cantidad ----------18 7

Segunda Pregunta: Qu divisa es la ms usada? Esta es un poco ms elaborada pero de nuevo nos basta con usar un GROUP BY. Tambin utilizamos TOP 1 para quedarnos slo con el valor ms alto despus de ordenar la suma de manera descendente. SELECT TOP 1 FROM Movimientos ORDER BY SUM(Cantidad) DESC Divisa -------------------------------------Yen (1 filas afectadas) Divisa, GROUP SUM(Cantidad) BY Suma Divisa Suma ----------75000

Tercera pregunta: Cantidad de cada tipo de transaccin en cada tipo de divisa? Aqu tenemos que agrupar por TipoTransaccion y Divisa para obtener la suma de las cantidades por esos conceptos. Podemos ver cuantos Euros han salido o cuantos dlares han entrado. SELECT TipoTransaccion, Divisa, SUM(Cantidad) Cantidad FROM Movimientos GROUP BY TipoTransaccion, Divisa ORDER BY TipoTransaccion TipoTransaccion Divisa Cantidad --------------------------- ------------------ ----------Entrada Dolar 6200 Entrada Euro 10600 Entrada Libra 4500 Entrada Yen 45000 Salida Dolar 7000 Salida Libra 1700

Salida (7 filas afectadas)

Yen

30000

Sin embargo esto no responde a todas las preguntas que podemos hacer. Cuarta pregunta: Y si quiero la informacin agrupada de ms maneras? Por ejemplo para saber el total entrante, o el balance de Yenes habr que hacer clculos adicionales o bien con nuevas consultas o bien en nuestra aplicacin cliente. Pero ahora tenemos WITH CUBE que nos permite crear nuevas dimensiones en nuestras consultas. Cuando usamos esta clusula es como si estuvisemos haciendo a la vez todos los GROUP BY posibles y adems mostrndolos en un nico resultset. Aadamos el WITH CUBE a la sentencia anterior SELECT TipoTransaccion, Divisa, SUM(Cantidad) Cantidad FROM Movimientos GROUP BY TipoTransaccion, Divisa WITH CUBE TipoTransaccion Divisa Cantidad ------------------------------ ---------------------------- ----------Entrada Dolar 6200 Entrada Euro 10600 Entrada Libra 4500 Entrada Yen 45000 Entrada NULL 66300 Salida Dolar 7000 Salida Libra 1700 Salida Yen 30000 Salida NULL 38700 NULL NULL 105000 NULL Dolar 13200 NULL Euro 10600 NULL Libra 6200 NULL Yen (14 filas afectadas)

75000

Aqu hay unos cuantos cambios. Primero vemos que sin necesidad de decirlo los datos se han ordenado por TipoTransaccion y dentro de TipoTransaccion por Divisa. Adems aparecen varios NULL por el medio de la tabla. Pero no os preocupis que todo va bien y vamos a explicar este resultado con calma. Ahora cada fila es una de las posibles combinaciones de TipoTransaccion con Divisa, y las filas que contienen un NULL se tienen que leer pensando que donde est el NULL debera poner <todas>. Es decir la fila NULL Dolar 13200

Quiere decir que la cantidad total de Dlares tanto en entradas como en salidas (todos los TiposTransaccipn) es 13200 La fila Entrada NULL 66300

Quiere decir que hay un valor total de 66300 para todas las entradas (es decir, para todas las divisas) y por ltimo la fila NULL NULL 105000

Nos indica que el total de movimientos (todos los TipoTransaccion) de entrada y salida en cualquier divisa (todas las divisas) es de 105000 Como vemos el NULL representa un super agregado en la columna en la que est colocado. Este tipo de NULL no lo debemos confundir con un NULL normal. Ya sabis que un NULL normal indica que desconocemos el valor mientras que este NULL indica una agrupacin. Vamos a insertar una nueva fila en nuestra tabla INSERT INTO Movimientos (TipoTransaccion, Divisa, Cantidad) VALUES ('Entrada', NULL, 2000) Qu ocurre ahora si repetimos la consulta? Quinta pregunta: cmo sabemos cual de los NULL es un super agregado y cual es un NULL de verdad? Hay una funcin llamada GROUPING que nos dice cuando nuestro NULL es de verdad y cuando no. Esta funcin nos devuelve un 1 si el nombre de la columna pasada como parmetro se usa como resumen y un 0 si no es as. Veamos un ejemplo SELECT TipoTransaccion, Divisa, 'Todas las Divisas'=GROUPING(Divisa), SUM(Cantidad) Cantidad FROM Movimientos GROUP BY TipoTransaccion, Divisa WITH CUBE TipoTransaccion Divisa Todas las Divisas ------------------------------ ------------------- --------------------------- ----------Entrada NULL 0 Entrada Dolar 0 Entrada Euro 0 Entrada Libra 0 Entrada Yen 0 Entrada NULL 1 Salida Dolar 0 Salida Libra 0 Salida Yen 0 Salida NULL 1 NULL NULL 1 NULL NULL 0 NULL Dolar 0 NULL Euro 0 NULL Libra 0 NULL Yen 0 (16 filas afectadas) Cantidad 2000 6200 10600 4500 45000 68300 7000 1700 30000 38700 107000 2000 13200 10600 6200 75000

Como veis hay dos tipos de NULL en la columna de divisas. Las que corresponden al ltimo registro que insertamos que tiene un NULL en divisa, y al que la funcin GROUPING le asocia un 0, y el NULL que podemos traducir por <Todas las divisas> al que la funcin GROUPING le asocia un 1. Sexta pregunta: Podemos mejorar el aspecto del resultado? Ahora mezclamos estas funciones nuevas con dos funciones conocidas, CASE e ISNULL para darle un aspecto ms elegante al Resulset obtenido. SELECT TipoTransaccion,

'Divisa'= CASE

END, SUM(Cantidad) Cantidad FROM Movimientos GROUP BY TipoTransaccion, Divisa WITH CUBE

WHEN GROUPING(Divisa)=1 THEN 'Todas' ELSE ISNULL(Divisa, 'N/D')

TipoTransaccion Divisa Cantidad ---------------------------------------- -------------------------------------- ----------Entrada N/D 2000 Entrada Dolar 6200 Entrada Euro 10600 Entrada Libra 4500 Entrada Yen 45000 Entrada Todas 68300 Salida Dolar 7000 Salida Libra 1700 Salida Yen 30000 Salida Todas 38700 NULL Todas 107000 NULL N/D 2000 NULL Dolar 13200 NULL Euro 10600 NULL Libra 6200 NULL Yen 75000 (16 filas afectadas) Todo queda ms claro en este resultado. Donde pone todas en la columna de divisas quiere decir precisamente eso, y donde pone N/D pues quiere decir no disponible. Sptima pregunta: Podemos saberlo todo? Pues ahora ya s. Vamos a poner la consulta que nos devuelve toda la informacin que podemos pedir a los datos iniciales. SELECT 'TipoTransacion'= CASE WHEN GROUPING(TipoTransaccion)=1 THEN 'Todas' ELSE ISNULL(TipoTransaccion, 'N/D') END, 'Divisa'= CASE WHEN GROUPING(Divisa)=1 THEN 'Todas' ELSE ISNULL(Divisa, 'N/D') END, SUM(Cantidad) Cantidad FROM Movimientos GROUP BY TipoTransaccion, Divisa WITH CUBE Cantidad 2000 6200 10600 4500 45000 68300 7000

TipoTransacion Divisa ---------------------------------------- -------------------------------------- ----------Entrada N/D Entrada Dolar Entrada Euro Entrada Libra Entrada Yen Entrada Todas Salida Dolar

Salida Salida Salida Todas Todas Todas Todas Todas Todas (16 filas afectadas)

Libra Yen Todas Todas N/D Dolar Euro Libra Yen

1700 30000 38700 107000 2000 13200 10600 6200 75000

De esta consulta podemos sacar todas las respuestas a cualquier pregunta que nos hagan sobre los datos iniciales. Octava pregunta: Y qu pasa con el ROLLUP? Mientras que WITH CUBE genera un conjunto de resultados que muestra agregados para todas las combinaciones de valores de las columnas seleccionadas, WHIT ROLLUP genera un conjunto de resultados que muestra agregados para una jerarqua de valores de las columnas seleccionadas. Es decir, con CUBE aparecen los resultado totalizados por TipoTransaccion, por Divisa, y por totales absolutos, mientras que con ROLLUP slo apareceran los totales agrupados por lo que nosostros indiquemos. Vemoslo agrupando por TipoTransaccion: SELECT 'TipoTransacion'= CASE WHEN GROUPING(TipoTransaccion)=1 THEN 'Todas' ELSE ISNULL(TipoTransaccion, 'N/D') END, 'Divisa'= CASE WHEN GROUPING(Divisa)=1 THEN 'Todas' ELSE ISNULL(Divisa, 'N/D') END, SUM(Cantidad) Cantidad FROM Movimientos GROUP BY TipoTransaccion, Divisa WITH ROLLUP Cantidad 2000 6200 10600 4500 45000 68300 7000 1700 30000 38700 107000

TipoTransacion Divisa --------------------------------------- --------------------------------------- ----------Entrada N/D Entrada Dolar Entrada Euro Entrada Libra Entrada Yen Entrada Todas Salida Dolar Salida Libra Salida Yen Salida Todas Todas Todas (11 filas afectadas)

Obtenemos menos informacin que con WITH CUBE pero de manera ms clara. Adems muchas veces con esto ser suficiente Novena pregunta: Esto se parece al COMPUTE BY verdad?

Este tipo de consultas a alguno le traer a la memoria una clusula de SQL Server llamada COMPUTE BY, que hace prcticamente lo mismo pero de diferente manera. Ejecutemos esta consulta SELECT TipoTransaccion, Divisa, Cantidad FROM Movimientos ORDER BY TipoTransaccion, Divisa COMPUTE SUM(Cantidad) BY TipoTransaccion, Divisa TipoTransaccion -----------------------------Entrada Divisa NULL Cantidad ------------------------2000 ------------------------sum =========== 2000

TipoTransaccion Divisa Cantidad ------------------------------ ------------------------ ----------Entrada Dolar 1200 Entrada Dolar 5000

TipoTransaccion Divisa Cantidad ------------------------------ ------------------------- ----------Entrada Euro 4000 Entrada Euro 300 Entrada Euro 400 Entrada Euro 900 Entrada Euro 200 Entrada Euro 1300 Entrada Euro 700 Entrada Euro 2100 Entrada Euro 700

sum =========== 6200

TipoTransaccion Divisa Cantidad ------------------------------- -------------------------- ----------Entrada Libra 400 Entrada Libra 200 Entrada Libra 400 Entrada Libra 500 Entrada Libra 3000

sum =========== 10600

TipoTransaccion Divisa Cantidad ------------------------------- ----------------------------- ----------Entrada Yen 20000 Entrada Yen 25000

sum =========== 4500

TipoTransaccion Divisa Cantidad --------------------------------- ---------------------------- -----------

sum =========== 45000

Salida Salida Salida

sum =========== 7000 TipoTransaccion Divisa Cantidad --------------------------------- ----------------------------- ----------Salida Libra 500 Salida Libra 300 Salida Libra 900 sum =========== 1700 TipoTransaccion Divisa Cantidad --------------------------------- ----------------------------- ----------Salida Yen 30000 sum =========== 30000 (34 filas afectadas) Es otra manera de obtener resultados agrupados, pero tiene un par de inconvenientes. El primero y ms importante es que el ROLLUP produce una salida una salida relacional que se pueda almacenar como una vista, utilizar en el FROM de otra consulta o enviar al cliente para ser manejada como un Recordset de Visual Basic. El resultado de un COMPUTE BY tiene una serie de filas adicionales un poco incmodas si queremos usar ese resultado para algo ms que mostrarselo al usuario. Y la segunda razn para no usarla es que Microsoft incluye el COMPUTE BY por compatibilidad y no recomienda su uso (en .Net olvidaros de usar COMPUTE BY) Dcima pregunta: Muy bonito todo esto, pero si lo hago con un montn de datos en varias tablas, no ser muy lento? S. Si la cantidad de datos a tratar es muy grande este tipo de consultas pueden consumir muchos recursos y tiempo, pero hay muchas soluciones para que esto no sea un problema. Por ejemplo cuando tenemos una consulta que va a resumir una serie de datos y la vamos a necesitar habitualmente podemos convertirla en una vista o guardar el resultado en una tabla, y as podemos recurrir al resultado sin perder tiempo volviendo a ejecutar la sentencia SQL. Siguiendo con nuestro ejemplo podemos almacenar el resultado que obtuvimos con el CUBE en una tabla nueva con SELECT . . . INTO SELECT 'TipoTransacion'= CASE WHEN GROUPING(TipoTransaccion)=1 THEN 'Todas' ELSE ISNULL(TipoTransaccion, 'N/D') END, 'Divisa'= CASE WHEN GROUPING(Divisa)=1 THEN 'Todas' ELSE ISNULL(Divisa, 'N/D') END, SUM(Cantidad) Cantidad INTO Resumen FROM Movimientos GROUP BY TipoTransaccion, Divisa WITH CUBE select * from resultado

Dolar Dolar Dolar

1000 2000 4000

Ahora podemos recurrir a la informacin ya tratada leyendo la tabla Resumen. ltima pregunta: Es esto todo? No, ni mucho menos. Aqu slo tenemos una muestra de lo que se puede hacer con lenguaje SQL para analizar la informacin que hay en nuestros datos. Y si alguien est interesado en esto del procesado analtico lo visto aqu ni siquiera es la punta del iceberg!! De todos modos es un comienzo

Potrebbero piacerti anche