Como pivotar datos en consultas SQL

A lo largo de mi vida profesional me he encontrado con la necesidad de crear salidas de datos en las que tenia los datos por filas en las tablas de la base de datos y la representación para el usuario requería columnas. El procedimiento por el cual se transforman filas en columnas se llama “pivotar”.

Vamos a partir de un ejemplo simple. Tenemos una tabla de ventas por mes en la que se almacena 4 campos: año, mes, cantidad e importe de venta mensual.

select * from VENTAS
ANYO MES CANTIDAD IMPORTE
2000 1 223 9587.66
2000 2 458 21593.4
2000 3 625 35051.4
2000 4 600 40539.87
2000 5 425 38067.3

(Existen datos para todos los meses de los años 2000, 2001 y 2003 )

Supongamos que necesitamos los datos en una tabla cruzada de Años contra meses. La primera forma de hacerlo que se nos suele ocurrir es obtener todas las tuplas de la tabla y con el lenguaje que estemos programando ir recorriendo fila por fila e ir pintando en una tabla los datos para cada año y mes uno a uno.
Con la pivotación de estos datos podemos ahorrarnos mucho trabajo y tiempo de calculo en nuestra aplicación.

La técnica consiste en agrupar por uno de los ejes de la tabla cruzada (en este caso he elegido el Año) y hacer un sumatorio por cada ocurrencia distinta del otro eje (Mes en este ejemplo), pero solo para unos valores determinados del otro eje. Para que esto funcione necesitamos que ambas columnas tengan valores discretos, o bien discretizarlos nosotros haciendo rangos.
Así nos quedará una tabla resultado con una fila por cada año del que haya datos en la tabla origen y una columna por cada mes que queramos calcular.
Esta es la consulta que nos calcula esto en MySQL. En este caso usamos la función IF de MySQL que evalúa el primer parámetro, si este es verdadero, nos devuelve el valor del segundo parámetro. En cualquier otro caso nos devuelve el valor del tercer parámetro.
Para muchas otras bases de datos (como oracle, o informix) se usa la función DECODE que tiene los mismos parámetros que esta.

select ANYO,
sum( if( MES=1, CANTIDAD, 0) ) JAN,
sum( if( MES=2, CANTIDAD, 0) ) FEB,
sum( if( MES=3, CANTIDAD, 0) ) MAR,
sum( if( MES=4, CANTIDAD, 0) ) APR,
sum( if( MES=5, CANTIDAD, 0) ) MAY,
sum( if( MES=6, CANTIDAD, 0) ) JUN,
sum( if( MES=7, CANTIDAD, 0) ) JUL,
sum( if( MES=8, CANTIDAD, 0) ) AUG,
sum( if( MES=9, CANTIDAD, 0) ) SEP,
sum( if( MES=10, CANTIDAD, 0) ) OCT,
sum( if( MES=11, CANTIDAD, 0) ) NOV,
sum( if( MES=12, CANTIDAD ,0) ) 'DEC'
from VENTAS
group by anyo

Este es el resulado que obtendremos:

ANYO JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
2000 223 458 625 600 425 917 1258 1369 687 125 59 80
2001 233 400 541 425 566 700 805 958 300 254 90 112
2003 125 250 369 402 587 800 1596 1047 587 224 68 0

Estas consultas se pueden complicar tanto como queramos pero esto es un ejemplo básico que nos da la idea de como se pivotan datos en consultas SQL.

Espero que le sirva a alguien de ayuda.

Saludos!