Creación de informes de referencias cruzadas. El Operador PIVOT.

Enviado por admin el Jue, 25/04/2019 - 09:02

A veces es necesario girar resultados de modo que, los datos en columnas se presentan en sentido horizontal y los datos en filas se presentan en forma vertical. Esto se conoce como la creación de una tabla dinámica ®, creando un informe de referencias cruzadas, o rotación de datos.
En primer lugar vamos a comenzar poniendo un ejemplo de cómo se debía realizar algo similar, aunque con mucha menos potencia en SQL Server 2000, en el que no disponíamos del operador PIVOT y donde teníamos que realizarlo mediante la función CASE.

Supongamos que disponemos de una estructura típica maestro detalle con las tablas Orders, Order Details y deseamos un informe similar al siguiente:

Ventas por año

 

             Ene - Feb - Mar - Abr - May - Jun - Jul - Ago - Sep - Oct - Nov - Dic

2000

2001

2002

...



 

 

La información que queremos mostrar, ya agrupada, la podemos obtener con la siguiente instrucción SELECT, aunque no en el formato que la necesitamos mostrar:

select year(O.OrderDate), month(O.OrderDate) as Mes, sum(D.Quantity) as Cantidad from [Order Details] D inner join Orders O on D.OrderID = O.OrderID where year(O.OrderDate) > 2000 group by P.ProductName, month(O.OrderDate) order by 1, 2

El resultado obtenido es:

 

Producto - Mes - Cantidad

2000 - 1 - 97

2000 - 2 - 10

2000 - 3 - 73

2000 - 4 - 34

........

2001 - 1 - 55

Ahora, si queremos mostrarlo según el formato que hemos definido anteriormente, y estamos utilizando SQL Server 2000, tenemos que recurrir a la función CASE, como se muestra a continuación:

select year(O.OrderDate),

sum(CASE WHEN month(O.OrderDate) = 1 THEN D.Quantity ELSE 0 END) AS Ene,

sum(CASE WHEN month(O.OrderDate) = 2 THEN D.Quantity ELSE 0 END) AS Feb,

sum(CASE WHEN month(O.OrderDate) = 3 THEN D.Quantity ELSE 0 END) AS Mar,

sum(CASE WHEN month(O.OrderDate) = 4 THEN D.Quantity ELSE 0 END) AS Abr,

sum(CASE WHEN month(O.OrderDate) = 5 THEN D.Quantity ELSE 0 END) AS May,

sum(CASE WHEN month(O.OrderDate) = 6 THEN D.Quantity ELSE 0 END) AS Jun,

sum(CASE WHEN month(O.OrderDate) = 7 THEN D.Quantity ELSE 0 END) AS Jul,

sum(CASE WHEN month(O.OrderDate) = 8 THEN D.Quantity ELSE 0 END) AS Ago,

sum(CASE WHEN month(O.OrderDate) = 9 THEN D.Quantity ELSE 0 END) AS Sep,

sum(CASE WHEN month(O.OrderDate) = 10 THEN D.Quantity ELSE 0 END) AS Oct,

sum(CASE WHEN month(O.OrderDate) = 11 THEN D.Quantity ELSE 0 END) AS Nov,

sum(CASE WHEN month(O.OrderDate) = 12 THEN D.Quantity ELSE 0 END) AS Dic

from [Order Details] D inner join Orders O on D.OrderID = O.OrderID

where O.OrderDate between '20000101' and '20101231'

group by year(O.OrderDate)

order by 1

El resultado obtenido es:

                 Ene Feb Mar  Abr May Jun  Jul Ago  Sep Oct Nov Dic

2000              97  10   0    0  73  34  100   0   30  55  20 108

2001              50   0  20    0  60   0   14   0    0   6  20  20

2002              52  20  61   30  35  52   42  60  144   0  99   1

2003              60   0  60  106  35  24  125  30  135  10  65  15

...

 

Si ya disponemos de SQL Server 2005 o posteriores, entonces tendremos disponible una nueva funcionalidad que nos permite realizar de forma más sencilla este tipo de tareas. Esta funcionalidad nos la ofrece el operador PIVOT (en otra ocasión hablaremos del operador UNPIVOT). PIVOT nos permite convertir filas en columnas. Lo podemos incluir en la cláusula FROM de nuestras instrucciones SELECT.

select anio, [1] Ene, [2] Feb, [3] Mar, [4] Abr, [5] May, [6] Jun,

[7] Jul, [8] Ago, [9] Sep, [10] Oct, [11] Nov, [12] Dic

from (

-- select inicial, a pivotar. Podría ser una tabla

select year(O.OrderDate) as anio, month(O.OrderDate) as Mes,

D.Quantity as Cantidad

from [Order Details] D inner join Orders O on D.OrderID = O.OrderID

where O.OrderDate between '20000101' and '20101231'

) V PIVOT ( sum(Cantidad) FOR Mes IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12]) ) as PT

Como podéis comprobar, simplemente tenemos que usar la función PIVOT, a la cual le indicamos una función de agregado, la columna que queremos girar (pivotar) y desglosamos las columnas en las que queremos mostrar la información, esto nos permite utilizar ese desglose realizado como cualquier otra columna más en nuestra instrucción SELECT. La función PIVOT nos permite girar (pivotar), convirtiendo los valores únicos de una columna en varias columnas de salida, y realizando agregaciones para dichos valores.

Categoría