Usuário com melhor resposta
Ajuda PIVOT

Pergunta
-
Amigos,
Estou tentando executar o comando abaixo e não estou conseguindo. Porém quando troco o paramento [Jun 2 2009] para [02/06/2009] funciona corretamente. Poderiam me ajudar?
Código:--Captura MenorPeriodo Declare @menorPeriodo as SmallDateTime --Set @menorPeriodo = (Select Min(Convert (SmallDateTime,Cast(Dt_Relatorio as Char(11)),103)) as Dt_Relatorio From dbo.D_Pontual_CR_Relatorio_Oi) Set @menorPeriodo = ('2009-06-02') --Captura MaiorPeriodo Declare @maiorPeriodo as SmallDateTime --Set @maiorPeriodo = (Select Max(Convert (SmallDateTime,Cast(Dt_Relatorio as Char(11)),103)) as Dt_Relatorio From dbo.D_Pontual_CR_Relatorio_Oi) Set @maiorPeriodo = ('2009-06-03') --Inicializo periodo Declare @Periodos as VARCHAR(Max) Set @Periodos = '' -- Inicializa a variável @cmdSQL com a montagem do PIVOT -- O caractér ? será substituído pelo período obtido dinamicamente Declare @cmdSQL VARCHAR(Max) SET @cmdSQL = ('''SELECT Fx_Atraso, ? FROM (SELECT Fx_Atraso, Dt_Relatorio_Teste, Cast(Sum(Sld_Devedor) as Money) as Vl_Sld_Devedor FROM dbo.D_Pontual_CR_Relatorio_Oi Where UN In(''Varejo'', ''Varejo/Oi Conta Colaborador'', ''VARME'', ''VARRES'', ''VARRES/Oi Conta Colaborador'', ''VARRES/TOP'') Group By Fx_Atraso, Dt_Relatorio) AS TBO PIVOT (Sum(Vl_Sld_Devedor) FOR Dt_Relatorio_Teste In (?)) AS TPVT''') --Select @cmdSQL -- Montagem dos períodos WHILE @menorPeriodo <= @maiorPeriodo BEGIN SET @Periodos = @Periodos + '[' + CAST(@menorPeriodo AS CHAR(11)) + '],' SET @menorPeriodo = @menorPeriodo + 1 END -- Monta os períodos SET @Periodos = LEFT(@Periodos,LEN(@Periodos)-1) -- Substitui o ? pelo período montado dinamicamente SET @cmdSQL = REPLACE(@cmdSQL,'?',@Periodos) -- Executa o comando, opcionalmente dê um PRINT PRINT @cmdSQL EXEC (@cmdSQL)
Esse é o print do comando:
'SELECT Fx_Atraso, [Jun 2 2009],[Jun 3 2009] FROM (SELECT Fx_Atraso, Dt_Relatorio_Teste, Cast(Sum(Sld_Devedor) as Money) as Vl_Sld_Devedor FROM dbo.D_Pontual_CR_Relatorio_Oi Where UN In('Varejo', 'Varejo/Oi Conta Colaborador', 'VARME', 'VARRES', 'VARRES/Oi Conta Colaborador', 'VARRES/TOP') Group By Fx_Atraso, Dt_Relatorio) AS TBO PIVOT (Sum(Vl_Sld_Devedor) FOR Dt_Relatorio_Teste In ([Jun 2 2009],[Jun 3 2009])) AS TPVT'
Danielsegunda-feira, 22 de junho de 2009 17:39
Respostas
-
Boa Tarde,
Essa necessidade é um pouco atípica, mas é possível com alguns truques no seu algoritmo.WHILE @menorPeriodo <= @maiorPeriodo BEGIN IF EXISTS (SELECT * FROM D_Pontual_CR_Relatorio_Oi WHERE Dt_Relatorio = @menorPeriodo) BEGIN SET @Periodos = @Periodos + '[' + CAST(@menorPeriodo AS CHAR(11)) + '],' END SET @menorPeriodo = @menorPeriodo + 1 END
Assim, a montagem da coluna só irá acontecer quando houver pelo menos um registro na data especificada. Se suas necessidades de consulta começarem a evoluir dessa maneira, cogite seriamente em utilizar outra tecnologia (OWC, Reporting Services, Integration Services, etc). Banco de dados tradicional não é pra isso...
[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
Como importar e exportar imagens entre o SQL Server e o File System ? – Parte II
http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!612.entry
Classifique as respostas. O seu feedback é imprescindível- Marcado como Resposta dralves terça-feira, 23 de junho de 2009 17:03
- Não Marcado como Resposta dralves terça-feira, 23 de junho de 2009 17:03
- Sugerido como Resposta Gustavo Maia Aguiar terça-feira, 23 de junho de 2009 17:22
- Marcado como Resposta dralves terça-feira, 23 de junho de 2009 17:45
terça-feira, 23 de junho de 2009 16:15
Todas as Respostas
-
DrAlves,
Mas porque você deseja passar o valor neste formato Jun 2 2009?
Pedro Antonio Galvão Junior - MVP - Windows Server System - SQL Server/Coordenador de Projetos/DBAsegunda-feira, 22 de junho de 2009 18:06 -
Junior,
consegui acertar o formato e a consulta rodou perfeitamente. O formato foi 02/06/2009.
Porém tenho um dúvida. Como faço para excluir as colunas que possuem valores null. No caso seriam as colunas ( 14/05/2009
, 15/05/2009)
Vide exemplo:
Fx_Atraso 13-05-2009 14-05-2009 15-05-2009 NULL 136,81 NULL NULL 00 - A Vencer 92605,43 NULL NULL 01-01-1930 159424145 NULL NULL 02 - 31 - 60 98057545,7 NULL NULL 03 - 61 - 90 28825464,62 NULL NULL 04 - 91 - 120 36525109,21 NULL NULL 05 - 121 - 150 16794331,26 NULL NULL 06 - 151 - 180 12660473,32 NULL NULL 07 - 181 - 210 11040011,42 NULL NULL 08 - >210 324319889,6 NULL NULL
Danielsegunda-feira, 22 de junho de 2009 18:54 -
DrAlves,
Você deseja não exibir estas colunas quando elas possuirem valores nulos ou realmente deseja remover sua exibição?
Pedro Antonio Galvão Junior - MVP - Windows Server System - SQL Server/Coordenador de Projetos/DBAsegunda-feira, 22 de junho de 2009 20:02 -
Desejo excluir as colunas que estão nulas.
Danielsegunda-feira, 22 de junho de 2009 20:05 -
Conseguiu ver alguma coisa?
Danielsegunda-feira, 22 de junho de 2009 20:57 -
Marcelo bom dia,
conseguiu ver alguma coisa?
Desde já agradeço.
Danielterça-feira, 23 de junho de 2009 12:24 -
Bom dia Galera,
Alguem poderia ajudar?
Desde já agradeço.
Danielterça-feira, 23 de junho de 2009 13:54 -
Ola Daniel,
Daniel tentei algumas formas p/ eliminar esta coluna mas nenhuma deu certo... é facil eliminar linha qndo a linha é nula mas eliminar coluna quando a linha é nula é mais complexo :)
Tente eliminar esta coluna antes do pivot (qndo ela é linha ainda) acredito que vc pode obter algum sucesso.
Att.
Marcelo Fernandes
MCP, MCDBA, MCSA, MCTS. Se útil, classifique!!!terça-feira, 23 de junho de 2009 14:26 -
Mais essa coluna ainda não existe como o meu Pivot é dinamico, ou seja, eu pego a menor data e a maior data todo esse intervalo pode vir null, sendo assim, não tem como eliminar antes.
Andei pesquisando na Net e o Gustavo tem dois post muito bons, mais infelizmente não aborda nada com relação a isso.
Gustavo poderia me ajudar?
Marcelo obrigado pela ajuda.
Danielterça-feira, 23 de junho de 2009 14:35 -
Boa Tarde,
Essa necessidade é um pouco atípica, mas é possível com alguns truques no seu algoritmo.WHILE @menorPeriodo <= @maiorPeriodo BEGIN IF EXISTS (SELECT * FROM D_Pontual_CR_Relatorio_Oi WHERE Dt_Relatorio = @menorPeriodo) BEGIN SET @Periodos = @Periodos + '[' + CAST(@menorPeriodo AS CHAR(11)) + '],' END SET @menorPeriodo = @menorPeriodo + 1 END
Assim, a montagem da coluna só irá acontecer quando houver pelo menos um registro na data especificada. Se suas necessidades de consulta começarem a evoluir dessa maneira, cogite seriamente em utilizar outra tecnologia (OWC, Reporting Services, Integration Services, etc). Banco de dados tradicional não é pra isso...
[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
Como importar e exportar imagens entre o SQL Server e o File System ? – Parte II
http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!612.entry
Classifique as respostas. O seu feedback é imprescindível- Marcado como Resposta dralves terça-feira, 23 de junho de 2009 17:03
- Não Marcado como Resposta dralves terça-feira, 23 de junho de 2009 17:03
- Sugerido como Resposta Gustavo Maia Aguiar terça-feira, 23 de junho de 2009 17:22
- Marcado como Resposta dralves terça-feira, 23 de junho de 2009 17:45
terça-feira, 23 de junho de 2009 16:15 -
Blz Gustavo,
mais uma vez sua ajuda foi essencial. Tb Gostaria de agradecer ao Marcelo.
Uma ultima ajuda.
Existe a possibilidade de renomear uma coluna em especial, ou seja, conforme o PIVOT a coluna irá se chamar 13/05/2009 porém gostaria de chamar de Fechamento_Abril_2009. Isso é possível?
Danielterça-feira, 23 de junho de 2009 17:03 -
Olá Daniel,
Possível é. Bastaria que você adicionasse um Alias nas colunas. O problema é que o comando vai ficar ainda mais complexo.
Outra opção é persistir os dados em uma tabela temporária e posteriormente renomear as colunas com um cursor e a sp_rename.
Não sei a freqüência com que esse código será executado, mas é visível que a complexidade está aumentando significativamente. No futuro poderá ficar bem complicado de manter. Sugiro avaliar outras soluções.
[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
Como importar e exportar imagens entre o SQL Server e o File System ? – Parte II
http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!612.entry
Classifique as respostas. O seu feedback é imprescindívelterça-feira, 23 de junho de 2009 17:22 -
Ele é executado uma unica vez na semana e possui uma quantidade de 3.000 registros.
O eu fiz pra renomear foi carregar em uma tabela temporaria e renomear na mão, porém gostaria de deixar a consulta automatizada, ou seja, eu tenho que renomear somente a coluna que possui a menor data de vencimento para cada mês. Vide exemplo:
Fx_Atraso 13-05-2009 02-06-2009 09-06-2009 18-06-2009 23-06-2009 Unid NULL NULL 1.114 10.519 91.350 91.350 Empresarial 00 - A Vencer 405.168 24.717.777 448.355 8.542.084 8.542.084 Empresarial 01 - 0 - 30 38.568.790 10.487.249 28.440.217 40.527.700 32.528.038 Empresarial
Gostaria de pegar a primeira data de mai/2009(13-05-2009) e renomear para Fechamento_Abril_2009 e pegar a data de jun/2009(02-06-2009) e renomear para Fechamento_Maio_2009.
Segue código como está hj.
If exists(Select * From sysobjects Where Name = 'D_Pontual_CR_Relatorio_Fixa_Dinamica') Drop Table D_Pontual_CR_Relatorio_Fixa_Dinamica; --Captura MenorPeriodo Declare @menorPeriodo as SmallDateTime Set @menorPeriodo = (Select Min(Convert (SmallDateTime,Cast(Dt_Relatorio as Char(11)),103)) as Dt_Relatorio From dbo.D_Pontual_CR_Relatorio_Oi) --Set @menorPeriodo = ('2009-06-02') --Select CAST(@menorPeriodo AS CHAR(11)) --Captura MaiorPeriodo Declare @maiorPeriodo as SmallDateTime Set @maiorPeriodo = (Select Max(Convert (SmallDateTime,Cast(Dt_Relatorio as Char(11)),103)) as Dt_Relatorio From dbo.D_Pontual_CR_Relatorio_Oi) --Set @maiorPeriodo = ('2009-06-03') --Inicializo periodo Declare @Periodos as VARCHAR(Max) Set @Periodos = '' -- Inicializa a variável @cmdSQL com a montagem do PIVOT -- O caractér ? será substituído pelo período obtido dinamicamente Declare @cmdSQL VARCHAR(Max) SET @cmdSQL = ('SELECT Fx_Atraso, ?, Case When UN In(''Varejo'', ''Varejo/Oi Conta Colaborador'', ''VARME'', ''VARRES'', ''VARRES/Oi Conta Colaborador'', ''VARRES/TOP'') Then ''Varejo'' When UN In(''EMP'', ''EMP/Oi Conta Colaborador'') Then ''Empresarial'' When UN In(''GDC'', ''GDC/Oi Conta Colaborador'', ''KAC'', ''KAC/BRONZE'', ''KAC/BRONZE-CORP'', ''KAC/DIAMANTE'',''KAC/DIAMANTE-CORP'',''KAC/DIAMANTE-OUT'', ''KAC/NOVO CLIENTE'', ''KAC/OURO-CORP'',''KAC/PLATINA-CORP'', ''KAC/PRATA'', ''KAC/PRATA-CORP'', ''KAC/PRATA-GDC2'') Then ''Corporativo'' Else ''Outros'' End as UN Into D_Pontual_CR_Relatorio_Fixa_Dinamica FROM (SELECT Fx_Atraso, Dt_Relatorio, UN, Cast(Sum(Sld_Devedor) as Money) as Vl_Sld_Devedor FROM dbo.D_Pontual_CR_Relatorio_Fixa Group By Fx_Atraso, Dt_Relatorio, UN) AS TBO PIVOT (Sum(Vl_Sld_Devedor) FOR Dt_Relatorio In (?)) AS TPVT') --Select @cmdSQL -- Montagem dos períodos --WHILE @menorPeriodo <= @maiorPeriodo --BEGIN -- SET @Periodos = @Periodos + '[' + RIGHT(CONVERT(CHAR(10),@menorPeriodo,103),10) + '],' -- SET @menorPeriodo = @menorPeriodo + 1 --END WHILE @menorPeriodo <= @maiorPeriodo BEGIN IF EXISTS (SELECT * FROM D_Pontual_CR_Relatorio_Oi WHERE Dt_Relatorio = RIGHT(CONVERT(CHAR(10),@menorPeriodo,103),10)) BEGIN SET @Periodos = @Periodos + '[' + RIGHT(CONVERT(CHAR(10),@menorPeriodo,103),10) + '],' END SET @menorPeriodo = @menorPeriodo + 1 END --Select @Periodos -- Monta os períodos SET @Periodos = LEFT(@Periodos,LEN(@Periodos)-1) -- Substitui o ? pelo período montado dinamicamente SET @cmdSQL = REPLACE(@cmdSQL,'?',@Periodos) -- Executa o comando, opcionalmente dê um PRINT --PRINT @cmdSQL EXEC (@cmdSQL)
Danielterça-feira, 23 de junho de 2009 17:44 -
Gustavo,
conseguiu ver alguma coisa?
Danielterça-feira, 23 de junho de 2009 19:04 -
Olá Daniel,
Eu até tentei, mas além do código ficar absurdamente complexo, descobri que não é possível renomear colunas de tabelas temporárias.create table #t ( [13-05-2009] int, [14-05-2009] int, [04-06-2009] int, [07-06-2009] int) set language Brazilian declare @i int, @f int, @col varchar(20), @cmd varchar(1000) ;With Datas As ( select Name As Col, CAST(Name As SmallDateTime) As Data from tempdb.sys.columns where OBJECT_NAME(object_id,DB_ID('TempDb')) like '#t%'), Res As ( select Col, Data, MONTH(Data) As Mes From Datas), Sel As ( select Col, Data, Mes, ROW_NUMBER() Over (Partition By Mes Order By Data) As Pos from res) select @f = COUNT(*) from Sel Where Pos = 1 set @i = 1 set @col = '' while @i <= @f begin ;With Datas As ( select Name As Col, CAST(Name As SmallDateTime) As Data from tempdb.sys.columns where OBJECT_NAME(object_id,DB_ID('TempDb')) like '#t%'), Res As ( select Col, Data, MONTH(Data) As Mes From Datas), Sel As ( select Col, Data, Mes, ROW_NUMBER() Over (Partition By Mes Order By Data) As Pos from res), Rel As ( select Col, Data, Mes, Pos, ROW_NUMBER() Over (Order By Col) As Num from Sel where Pos = 1) select top 1 @cmd = 'Comando para substituir a coluna ' + COL + ' para Fechamento_' + DATENAME(M,DATEADD(M,-1,Data)) + '2009' from Rel where pos = 1 and Num = @i print @cmd set @col = (select top 1 Name from tempdb.sys.columns where OBJECT_NAME(object_id,DB_ID('TempDb')) like '#t%' and name > @col) set @i = @i + 1 end drop table #t
Veja que essa complexidade foi só para renomear as colunas de uma tabela temporária (se pudéssemos usar a sp_rename). Adicione esse código no código anterior e realmente teremos uma solução muito complexa. Reforço que você deve buscar outras soluções, pois, a SQL não é para isso.
[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
Como importar e exportar imagens entre o SQL Server e o File System ? – Parte II
http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!612.entry
Classifique as respostas. O seu feedback é imprescindívelterça-feira, 23 de junho de 2009 19:07 -
A minha tabela não é temporaria. Isso já facilitaria um pouco?
Danielterça-feira, 23 de junho de 2009 19:16 -
Olá Daniel,
Você teria que adaptar o meu código com a sp_rename. Essa procedure pode renomear colunas. Então você faria um sp_rename com o nome antigo e o nome novo que podem ser obtidos a partir do meu código (nossa dá até pregüiça (rs)).
[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
Como importar e exportar imagens entre o SQL Server e o File System ? – Parte II
http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!612.entry
Classifique as respostas. O seu feedback é imprescindívelterça-feira, 23 de junho de 2009 20:25 -
Tem algum exemplo utilizando o sp_rename?
Caso não tenha desde já agradeço pela ajuda.
Danielterça-feira, 23 de junho de 2009 20:32 -
Olá Daniel,
O Books OnLine tem o exemplo da sp_rename para renomear a coluna.
Você poderá utilizá-lo.
[ ]s,
Gustavo Maia Aguiar
http://gustavomaiaaguiar.spaces.live.com
Como importar e exportar imagens entre o SQL Server e o File System ? – Parte II
http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!612.entry
Classifique as respostas. O seu feedback é imprescindívelterça-feira, 23 de junho de 2009 20:43