Pular para o conteúdo

Fóruns SQL e PL/SQL Como montar essa SQL? Como montar essa SQL?

#91795
fsitja
Participante

    Olá, fiz umas alterações aqui e rodei o seguinte caso de testes:


    SQL> CREATE TABLE CYBELAR_CRESCABR
    2 (CONTRATO NUMBER,
    3 VLRCURSO NUMBER,
    4 DTVENDA DATE,
    5 FATURADO VARCHAR2(20),
    6 LOJA VARCHAR2(20));

    Table created

    SQL> begin
    2 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (12345678,1000,to_date('2009/09/01','YYYY/MM/DD'),'S','A');
    3 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (12345678,3000,to_date('2009/09/01','YYYY/MM/DD'),'S','A');
    4 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (12345678,25000,to_date('2009/10/01','YYYY/MM/DD'),'S','B');
    5 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (123456789,50000,to_date('2009/09/01','YYYY/MM/DD'),'S','B');
    6 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (123456789,50000,to_date('2009/09/01','YYYY/MM/DD'),'S','B');
    7 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (123456789,12000,to_date('2009/09/01','YYYY/MM/DD'),'S','B');
    8 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (88888888,300,to_date('2009/09/01','YYYY/MM/DD'),'S','B');
    9 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (88888888,250,to_date('2009/10/01','YYYY/MM/DD'),'S','A');
    10 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (88888888,500,to_date('2009/09/01','YYYY/MM/DD'),'S','A');
    11 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (999999999,7000,to_date('2009/10/01','YYYY/MM/DD'),'S','A');
    12 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (999999999,2000,to_date('2009/10/01','YYYY/MM/DD'),'S','B');
    13 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (88888888,1400,to_date('2009/09/01','YYYY/MM/DD'),'N','A');
    14 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (555555555,9000,to_date('2009/09/01','YYYY/MM/DD'),'N','B');
    15 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (555555555,17000,to_date('2009/10/01','YYYY/MM/DD'),'N','B');
    16 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (555555555,7999,to_date('2009/10/01','YYYY/MM/DD'),'N','A');
    17 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (999999999,1500,to_date('2009/09/01','YYYY/MM/DD'),'N','A');
    18 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (555555555,9000,to_date('2009/08/01','YYYY/MM/DD'),'N','B');
    19 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (987654321,100,to_date('2009/09/01','YYYY/MM/DD'),'N','X');
    20 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (987654321,150,to_date('2009/10/01','YYYY/MM/DD'),'N','X');
    21 Insert into "CYBELAR_CRESCABR" ("CONTRATO","VLRCURSO","DTVENDA","FATURADO","LOJA") values (987654321,1150,to_date('2009/10/01','YYYY/MM/DD'),'S','X');
    22 end;
    23 /

    PL/SQL procedure successfully completed

    SQL> commit;

    Commit complete

    SQL> select t.*,
    2 (vv + contratos) - oracle - pedidos_antigos + pedidos_atuais conferencia
    3 from
    4 (
    5 SELECT trunc(dtvenda, 'MM') dtvenda,
    6 faturado,
    7 c.loja,
    8 nvl(SUM(c.vlrcurso), 0) oracle,
    9 sum(case when length(contrato) = 9
    12 then c.vlrcurso else 0 end) contratos,
    13 first_value(sum(c.vlrcurso)) over (partition by loja order by
    14 case when faturado = 'N'
    15 and to_char(dtvenda, 'MM/YYYY')

    Segue o SQL apenas, basta mudar o mês de referência para testar nos seus dados.

    select t.*,
    (vv + contratos) - oracle - pedidos_antigos + pedidos_atuais conferencia
    from (select trunc(dtvenda, 'MM') dtvenda,
    faturado,
    c.loja,
    nvl(sum(c.vlrcurso), 0) oracle,
    sum(case when length(contrato) = 9
    then c.vlrcurso else 0 end) contratos,
    first_value(sum(c.vlrcurso)) over (partition by loja order by
    case when faturado = 'N'
    and to_char(dtvenda, 'MM/YYYY') < '10/2009'
    then 0 else 1 end, trunc(dtvenda, 'MM') desc) pedidos_antigos,
    first_value(sum(c.vlrcurso)) over (partition by loja order by
    case when faturado = 'N'
    and to_char(dtvenda, 'MM/YYYY') = '10/2009'
    then 0 else 1 end)pedidos_atuais
    from cybelar_crescabr c
    group by loja, trunc(dtvenda, 'MM'), to_char(dtvenda, 'MM/YYYY'), faturado) t
    where to_char(dtvenda, 'MM/yyyy') = '10/2009'
    and faturado = 'S'
    order by dtvenda, loja, faturado

    A ideia basicamente é de usar uma mesma agregação várias vezes, através do CASE para fazer os sums corretos. Para resolver as referências ao mês anterior eu pensei inicialmente em usar um lag, mas como notei que a regra estava elaborada demais, preferi montar uma janela móvel “falsa” no order by com partition by na loja, pegando sempre o mês anterior sem precisar fazer vários scans, apenas dois window sort.

    Qualquer problema ou dúvida, é só mandar.

    []’s
    Francisco.