Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Colunas dinâmicas - SQL Server - Meses como colunas


Seus dados já estão dinamizados, mas precisam ser dinamizados em um nível diferente. Acho que a melhor maneira de lidar com isso é desativá-lo primeiro e, em seguida, lidar com o nível de pivô correto em segundo lugar.

Etapa 1:desarticular

Você pode usar o SQL 2005 UNPIVOT comando, ou use uma técnica CROSS JOIN. Aqui estão exemplos de ambos. Observe que deixei de fora meses no meio para manter as coisas simples. Basta adicioná-los.
-- 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 linha é repetida 12 vezes, então uma instrução CASE extrai apenas um mês para cada linha, deixando os dados bem não dinamizados.
-- 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

Nenhum dos métodos é um vencedor claro de desempenho o tempo todo. Às vezes, um funciona melhor que o outro (dependendo dos dados que estão sendo dinamizados). O método UNPIVOT usa um Filter no plano de execução que o CROSS JOIN não usa.

Etapa 2:pivotar novamente

Agora, como usar os dados não dinâmicos. Você não disse como seu alguém estará consumindo isso, mas como você precisará colocar os dados em um arquivo de saída de algum tipo, proponho usar o SSRS (Sql Server Reporting Services), que vem com o SQL Server 2005 sem custo extra.

Basta usar a Matriz report objeto para dinamizar uma das consultas acima. Esse objeto determina com satisfação os valores de dados a serem transformados em rótulos de coluna no tempo de execução do relatório e parece exatamente o que você precisa. Se você adicionar uma coluna que formate a data exatamente como quiser, poderá ordenar pela coluna Mo, mas use a nova expressão como o rótulo da coluna.

O SSRS também possui uma ampla variedade de formatos e opções de agendamento disponíveis. Por exemplo, você pode enviar um arquivo do Excel por e-mail ou salvar uma página da Web em um compartilhamento de arquivos.

Por favor, deixe-me saber se eu deixei alguma coisa de fora.

Para quem gostaria de ver o código acima em ação, aqui está um script de criação para você:
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)