sql >> Base de Datos >  >> RDS >> Sqlserver

Columnas dinámicas - SQL Server - Meses como columnas

Sus datos ya están pivotados, pero deben pivotarse en un nivel diferente. Creo que la mejor manera de manejar esto es quitarle el pivote primero y luego manejar el nivel de pivote correcto en segundo lugar.

Paso 1:Deshacer pivote

Puede usar SQL 2005 UNPIVOT o utilice una técnica CROSS JOIN. Aquí hay ejemplos de ambos. Tenga en cuenta que dejé meses en el medio para simplificar las cosas. Solo agrégalos.

-- CROSS JOIN method (also works in SQL 2000)
SELECT
   P.Project,
   Mo =
      DateAdd(mm,
         X.MonthNum,
         DateAdd(yy, P.[Year] - 1900, '19000101')
      ),
   Amount = 
      CASE X.MonthNum
         WHEN 0 THEN Jan
         WHEN 1 THEN Feb
         WHEN 11 THEN Dec
      END
FROM
   ProjectData P
   CROSS JOIN (
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 11
   ) X (MonthNum)

Cada fila se repite 12 veces, luego una declaración CASE extrae solo un mes para cada fila, dejando los datos sin pivotar.

-- UNPIVOT method
SELECT
    P.Project,
    Mo =
       DateAdd(mm,
          Convert(int, P.MonthNum),
          DateAdd(yy, P.[Year] - 1900, '19000101')
       ),
    P.Amount
FROM
   (
      SELECT Project, [Year], [0] = Jan, [1] = Feb, [11] = Dec
      FROM ProjectData
   ) X UNPIVOT (Amount FOR MonthNum IN ([0], [1], [11])) P

DROP TABLE ProjectData

Ninguno de los métodos es un claro ganador de rendimiento todo el tiempo. A veces, uno funciona mejor que el otro (dependiendo de los datos que se pivote). El método UNPIVOT usa un filtro en el plan de ejecución que CROSS JOIN no usa.

Paso 2:Pivote de nuevo

Ahora, cómo usar los datos no pivotados. No dijiste cómo tu alguien consumirá esto, pero como necesitará colocar los datos en un archivo de salida de algún tipo, propongo usar SSRS (Sql Server Reporting Services), que viene con SQL Server 2005 sin cargo adicional.

Simplemente use la Matrix informe de objeto para pivotar una de las consultas anteriores. Este objeto determina felizmente los valores de datos para convertirlos en etiquetas de columna en el tiempo de ejecución del informe y suena exactamente como lo que necesita. Si agrega una columna que formatea la fecha exactamente como lo desea, puede ordenar por la columna Mo, pero use la nueva expresión como la etiqueta de la columna.

SSRS también tiene una amplia variedad de formatos y opciones de programación disponibles. Por ejemplo, puede hacer que envíe por correo electrónico un archivo de Excel o guarde una página web en un recurso compartido de archivos.

Por favor, avíseme si me he dejado algo fuera.

Para cualquiera que desee ver el código anterior en acción, aquí hay un script de creación para usted:

USE tempdb

CREATE TABLE ProjectData (
    Project varchar(10),
    [Year] int,
    Jan decimal(15, 2),
    Feb decimal(15, 2),
    Dec decimal(15, 2)
)

SET NOCOUNT ON

INSERT ProjectData VALUES ('11-11079', 2008, 0.0, 0.0, 75244.90)
INSERT ProjectData VALUES ('11-11079', 2009, 466.0, 0.0, 0.0)
INSERT ProjectData VALUES ('11-11079', 2010, 855.0, 0.0, 0.0)
INSERT ProjectData VALUES ('01-11052', 2009, 56131.0, 0.0, 0.0)