Select com periodos independentes
18/11/2005
0
Criei uma consulta com um select principal agrupando por codigo de produto e dentro deste select eu possuo 10 sub-selects que equivalem a periodos diferentes dentro da faixa de datas do periodo do select principal e cada sub-select desse me retorna um valor total de um periodo relacionado pelo codigo de material com o select principal, segue ex: da query abaixo:
SELECT P.D2_COD CODIGO, (SELECT SUM(P1.D2_TOTAL) TOTAL1 FROM SD2010 P1 WITH(INDEX=SD20106) , SF4010 SF41 WHERE P.D2_COD=P1.D2_COD AND P1.D2_EMISSAO BETWEEN ´20050701´ AND ´20050701´ AND P1.D_E_L_E_T_ <> ´*´ AND P1.D2_TP IN (´PA´,´MR´) AND P1.D2_TES=SF41.F4_CODIGO AND SF41.D_E_L_E_T_ <> ´*´ AND SF41.F4_DUPLIC=´S´ AND SF41.F4_ESTOQUE<>´´ ) PERIODO1, (SELECT SUM(P2.D2_TOTAL) AS TOTAL2 FROM SD2010 P2 WITH(INDEX=SD20106) , SF4010 SF42 WHERE P.D2_COD=P2.D2_COD AND P2.D2_EMISSAO BETWEEN ´20050702´ AND ´20050702´ AND P2.D_E_L_E_T_ <> ´*´ AND P2.D2_TP IN (´PA´,´MR´) AND P2.D2_TES=SF42.F4_CODIGO AND SF42.D_E_L_E_T_ <> ´*´ AND SF42.F4_DUPLIC IN (´S´) AND SF42.F4_ESTOQUE IN (´S´,´N´) ) AS PERIODO2, (SELECT SUM(P3.D2_TOTAL) AS TOTAL3 FROM SD2010 P3 WITH(INDEX=SD20106) , SF4010 SF43 WHERE P.D2_COD=P3.D2_COD AND P3.D2_EMISSAO BETWEEN ´20050703´ AND ´20050703´ AND P3.D_E_L_E_T_ <> ´*´ AND P3.D2_TP IN (´PA´,´MR´) AND P3.D2_TES=SF43.F4_CODIGO AND SF43.D_E_L_E_T_ <> ´*´ AND SF43.F4_DUPLIC IN (´S´) AND SF43.F4_ESTOQUE IN (´S´,´N´) ) AS PERIODO3, (SELECT SUM(P4.D2_TOTAL) AS TOTAL4 FROM SD2010 P4 WITH(INDEX=SD20106) , SF4010 SF44 WHERE P.D2_COD=P4.D2_COD AND P4.
Ela está funcionando, mas está consumindo boa parte dos recursos do servidor sql server, tem outra maneira de criar está consulta ou é impossível ? na realidade, eu estou utilizando o tipo sub-select correlacionado.
Rogerio Amorim
Rogerio_amorim
Posts
18/11/2005
Emerson Nascimento
SELECT P.D2_COD CODIGO, SUM( case when P.D2_EMISSAO = ´20050701´ then P.D2_TOTAL else 0 ) PERIODO1, SUM( case when P.D2_EMISSAO = ´20050702´ then P.D2_TOTAL else 0 ) PERIODO2, SUM( case when P.D2_EMISSAO = ´20050703´ then P.D2_TOTAL else 0 ) PERIODO3, SUM( case when P.D2_EMISSAO = ´20050704´ then P.D2_TOTAL else 0 ) PERIODO4, SUM(P.D2_TOTAL) TOTALGERAL, SUM(P.D2_ICMSRET) TOTALICM, SUM(P.D2_VALIPI) TOTALIPI, SUM(D2_VALFRE) TOTALFRE, B.B1_DESC DESCRICAO FROM SD2010 P WITH(INDEX=SD20106) INNER JOIN SB1010 B WITH(INDEX=SB10101) ON (B.B1_COD = P.D2_COD AND B.D_E_L_E_T_ <> ´*´) LEFT JOIN SF4010 SF4 ON (SF4.F4_CODIGO = P.D2_TES AND SF4.D_E_L_E_T_ <> ´*´ AND SF4.F4_DUPLIC=´S´) WHERE P.D2_EMISSAO BETWEEN ´20050701´ AND ´20050704´ AND P.D_E_L_E_T_ <> ´*´ AND P.D2_TP IN (´PA´,´MR´) AND AND SF4.F4_ESTOQUE<>´´ GROUP BY P.D2_COD, B.B1_DESC ORDER BY B.B1_DESC
22/11/2005
Rogerio_amorim
Mas acredito que desse jeito não funcionaria pq os periodos são fixados da seguinte maneira, ex:
Periodo principal: 01/10/2005 a 31/10/2005
´1 periodo´ informado pelo usuario: 15/10/2005 (01/10/05 a 15/10/05)
´2 periodo´ informado pelo usuario: 31/10/2005 (16/10/05 a 31/10/05)
Quer dizer o usuário poderá tirar um relatorio de faturamento de uma semana ou até de um ano, mas ele está fixado em até 10 periodos. No seu exemplo ele checa se é igual a determinada data e soma, mas eu preciso que faça a soma dentro dos periodos que usuário informou seguindo o padrão acima, o que eu realmente não entendi foi o seguinte: ´SUM( case when P.D2_EMISSAO = ´20050701´
then P.D2_TOTAL else 0 ) PERIODO1,´
Vc poderia explicar melhor ???
Rogerio Amorim
22/11/2005
Emerson Nascimento
then P.D2_TOTAL else 0 ) PERIODO1,´ será utilizado para substituir os vários sub-selects que você montou. esses sub-selects é que estão sobrecarregando seu servidor.
a instrução acima diz para efetuar a soma no PERIODO1 somente se o valor de P.D2_EMISSAO for igual a ´20050701´; caso contrário acrescenta 0 (zero) à soma.
no seu caso deveria ser algo como:
SELECT P.D2_COD CODIGO, SUM( case when (P.D2_EMISSAO between ´20051001´ and ´20051015´) then P.D2_TOTAL else 0 ) PERIODO1, SUM( case when (P.D2_EMISSAO between ´20051016´ and ´20051031´) then P.D2_TOTAL else 0 ) PERIODO2, SUM(P.D2_TOTAL) TOTALGERAL, SUM(P.D2_ICMSRET) TOTALICM, SUM(P.D2_VALIPI) TOTALIPI, SUM(D2_VALFRE) TOTALFRE, B.B1_DESC DESCRICAO FROM SD2010 P WITH(INDEX=SD20106) INNER JOIN SB1010 B WITH(INDEX=SB10101) ON (B.B1_COD = P.D2_COD AND B.D_E_L_E_T_ <> ´*´) LEFT JOIN SF4010 SF4 ON (SF4.F4_CODIGO = P.D2_TES AND SF4.D_E_L_E_T_ <> ´*´ AND SF4.F4_DUPLIC=´S´) WHERE P.D2_EMISSAO BETWEEN ´20051001´ AND ´20051031´ AND P.D_E_L_E_T_ <> ´*´ AND P.D2_TP IN (´PA´,´MR´) AND AND SF4.F4_ESTOQUE<>´´ GROUP BY P.D2_COD, B.B1_DESC ORDER BY B.B1_DESC
ou seja: você monta os períodos como desejado, em função do período principal (que está no where)
p.s: você está fazendo isso para uso com o software da microsiga?
22/11/2005
Rogerio_amorim
Rogerio Amorim
22/11/2005
Rogerio_amorim
SELECT P.D2_COD CODIGO, case when P.D2_EMISSAO between ´20051001´ and ´20051015´ then SUM(P.D2_TOTAL) else 0 END PERIODO1, case when P.D2_EMISSAO between ´20051016´ and ´20051031´ then SUM(P.D2_TOTAL) else 0 END PERIODO2, SUM(P.D2_TOTAL) TOTALGERAL, SUM(P.D2_ICMSRET) TOTALICM, SUM(P.D2_VALIPI) TOTALIPI, SUM(D2_VALFRE) TOTALFRE, B.B1_DESC DESCRICAO FROM SD2010 P WITH(INDEX=SD20106) INNER JOIN SB1010 B WITH(INDEX=SB10101) ON (B.B1_COD = P.D2_COD AND B.D_E_L_E_T_ <> ´*´) LEFT JOIN SF4010 SF4 ON (SF4.F4_CODIGO = P.D2_TES AND SF4.D_E_L_E_T_ <> ´*´ AND SF4.F4_DUPLIC=´S´) WHERE P.D2_EMISSAO BETWEEN ´20050101´ AND ´20051031´ AND P.D_E_L_E_T_ <> ´*´ AND P.D2_TP IN (´PA´,´MR´) AND SF4.F4_ESTOQUE<>´´ GROUP BY P.D2_COD, B.B1_DESC, P.D2_EMISSAO ORDER BY B.B1_DESC
Clique aqui para fazer login e interagir na Comunidade :)