Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

tiago.uepa

Converter linhas em colunas PIVOT

Recommended Posts

Bom dia galera, sou novo aqui no fórum e aprendendo SQL, podem me ajudar a resolver esta query?

Preciso transformar o campo "periodo" em coluna, andei pesquisando e tentei usar o PIVOT, mas não consegui encaixá-lo na query:

SELECT
DISTINCT VEN.APELIDO,
TO_CHAR(CAB.DTNEG, 'YYYY"/"MM') AS PERIODO,
SUM (CASE WHEN (CAB.CODTIPOPER IN (40,44,50,47,87)) THEN ITE.QTDNEG
WHEN (CAB.CODTIPOPER IN (13,53,45,58)) THEN ( ITE.QTDNEG * (-1) ) ELSE 0
END )QUANTIDADE

FROM TGFCAB CAB
JOIN TGFITE ITE ON (ITE.NUNOTA = CAB.NUNOTA )
JOIN TGFPRO PRO ON (PRO.CODPROD = ITE.CODPROD)
JOIN TGFVEN VEN ON (VEN.CODVEND=CAB.CODVEND)
WHERE
(CAB.STATUSNFE = 'A' OR CAB.CODTIPOPER IN (13,53,45,58))
AND (PRO.REFERENCIA IS NOT NULL OR (PRO.REFERENCIA IS NULL AND CAB.CODPARC = '4925' ))
AND PRO.USOPROD 'M'
AND CAB.CODTIPOPER IN (40,44,50,47,87,13,53,45,58)
AND CAB.DTNEG BETWEEN :PERIODO.INI AND :PERIODO.FIN
AND (CAB.CODVEND = :VENDEDOR OR :VENDEDOR IS NULL)
AND (PRO.CODPROD = :CODIGOPROD OR :CODIGOPROD IS NULL)
AND (CAB.CODEMP =:EMPRESA OR :EMPRESA IS NULL)
AND CAB.CODVEND 0
GROUP BY VEN.APELIDO, TO_CHAR(CAB.DTNEG, 'YYYY"/"MM')
ORDER BY PERIODO DESC


Este é o resultado da query de acordo com PERIODO e outros dados informados pelo usuário nas variáveis:

APELIDO               PERIODO      QUANTIDADE

DAVI.REP               12/2015            29
EDSON.REP           12/2015           487
JOSE.REP              12/2015           366
SALVADOR.REP     12/2015           707
DAVI.REP                01/2016           50
EDSON.REP           01/2016           122
JOSE.REP               01/2016           75
SALVADOR.REP     01/2016            373


Mas preciso desta forma:

APELIDO                 12/2015     01/2016

DAVI.REP                   29             50
EDSON.REP             487            122
JOSE.REP                 366            75
SALVADOR.REP       707            373

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa tarde Motta,

Então, eu já tentei usar o pivot, mas não consegui encaixar corretamente dentro da query e o case acredito que nao dá certo pra esse caso pq não posso criar o case indicando os meses pois o período tem que ser dinamico.

poderia me ajudar a usar o pivot dentro da minha query?

obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

O problema do PIVOT e do CASE é justo este não ser dinâmico.

Eu já fia algo assim

SELECT SUM(CASE WHEN TO_CHAR(DTNEG,'YYYYMM') =  TO_CHAR(ADD_MONTHS(SYSDATE,-4,'YYYYMM')
                THEN QTDNEG  ELSE 0) MES_MENOS4,
       SUM(CASE WHEN TO_CHAR(DTNEG,'YYYYMM') =  TO_CHAR(ADD_MONTHS(SYSDATE,-3,'YYYYMM')
                THEN QTDNEG  ELSE 0) MES_MENOS3,
       SUM(CASE WHEN TO_CHAR(DTNEG,'YYYYMM') =  TO_CHAR(ADD_MONTHS(SYSDATE,-2,'YYYYMM')
                THEN QTDNEG  ELSE 0) MES_MENOS2,
       SUM(CASE WHEN TO_CHAR(DTNEG,'YYYYMM') =  TO_CHAR(ADD_MONTHS(SYSDATE,-1,'YYYYMM')
                THEN QTDNEG  ELSE 0) MES_MENOS1,
       SUM(CASE WHEN TO_CHAR(DTNEG,'YYYYMM') =  TO_CHAR(SYSDATE,'YYYYMM')
                THEN QTDNEG  ELSE 0) MES_CORRENTE

Na aplicação se monta o nome da coluna de forma dinâmica também.

O problema aqui é que temos um número "fixo" de colunas , mas ao menos , quando vira o mês não precisa alterar a sql.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então, o não ser dinâmico que complica, pois é para uma analise de acompanhamento de metas de representante, dai o Gerente escolhe o período em um filtro no relatório.

Até consegui progredir com o PIVOT tratando apenas por mes, vou tentar agora tratar o ano, se conseguisse tratar este FOR (PERIODO)IN ('01' AS JAN tornando janeiro variavel de acordo com periodo escolhido no filtro do relatório ai daria pra deixá-lo dinamico

select *
from ( SELECT DISTINCT VEN.APELIDO, TO_CHAR(CAB.DTNEG, 'MM') AS PERIODO,
SUM (CASE WHEN (CAB.CODTIPOPER IN (40,44,50,47,87)) THEN ITE.QTDNEG
WHEN (CAB.CODTIPOPER IN (13,53,45,58)) THEN ( ITE.QTDNEG * (-1) ) ELSE 0
END )QUANTIDADE
FROM TGFCAB CAB
JOIN TGFITE ITE ON (ITE.NUNOTA = CAB.NUNOTA )
JOIN TGFPRO PRO ON (PRO.CODPROD = ITE.CODPROD)
JOIN TGFVEN VEN ON (VEN.CODVEND=CAB.CODVEND)
WHERE (CAB.STATUSNFE = 'A' OR CAB.CODTIPOPER IN (13,53,45,58))
AND (PRO.REFERENCIA IS NOT NULL OR (PRO.REFERENCIA IS NULL AND CAB.CODPARC = '4925' ))
AND PRO.USOPROD <> 'M' AND CAB.CODTIPOPER IN (40,44,50,47,87,13,53,45,58) AND
CAB.DTNEG BETWEEN '01/12/2015' AND '30/12/2016'
AND CAB.CODVEND <>0
GROUP BY VEN.APELIDO, TO_CHAR(CAB.DTNEG, 'MM') )
PIVOT (SUM (QUANTIDADE) AS QUANTIDADE
FOR (PERIODO)IN ('01' AS JAN, '02' AS FEV, '03' AS MAR, '04' AS ABR, '05' AS MAI, '06' AS JUN, '07' AS JUL, '08' AS AGO, '09' AS SETB, '10' AS OUTB, '11' AS NOV, '12' AS DEZ ))

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mas a vantagem que já tive do PIVOT em relação ao CASE é que no CASE ele gerava linhas nulas no relatório em função do range do período informado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

O que pode ser uma desvantagem pois em alguns casos o usuário quer ver as linhas zeradas.

Uma solução pode ser montar o sql de forma dinâmica é executar via EXECUTE IMMEDIATE

Outra solução é gerar o dado bruto é resolver na camada de aplicação , tipo um Crystal Reports ou outro gerador , aí fica dinamico

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom dia,

É que o CASE que montei retornava linhas zeradas mas em função do range do período, na verdade era dado null.

Mas apresentei este com o PIVOT para o Gerente Comercial e já resolveu para analise dele pelo período anual mesmo.

Muito obrigado pela ajuda e atenção.

abraço

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.