Jump to content
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

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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 ))

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.