none
Select ou CTE ajuda RRS feed

  • Pergunta

  • Olá a todos,
    Preciso da seguinte ajuda:

    Tabela SAIDA (vendas)
    Preciso obter o total geral das vendas no periodo

    Select SUM(S2.vltotal) VlTotal From saidaitem S2 Where (S2.DataSaida >= '03/01/2012' AND S2.DataSaida <= '03/30/2012'))

    Depois preciso obter o total por cliente e achar o percentual que cada cliente representa do total geral das vendas

    o Select abaixo esta funcionando perfeitamente, mas demora de 2 a 3 min.
    Note que o select repete o calculo do total geral das vendas para cada cliente, o que nao seria necessario pois o total geral das vendas é o mesmo para todos os clientes.

    Select S1.codcli, Cli.rsocial
           ,SUM(S1.vltotal) VALOR_TOTAL_DO_CLIENTE
           ,ROUND((SUM(S1.vltotal) * 100.00 /
           ( Select SUM(S2.vltotal) VlTotal From saida S2 Where (S2.DataSaida >= '03/01/2012' AND S2.DataSaida <= '03/30/2012'))
            ),2) Percent
           ,( Select SUM(S3.vltotal) VlTotal From saida S3 Where (S3.DataSaida >= '03/01/2012' AND S3.DataSaida <= '03/30/2012')) VL_TOTAL_GERAL
    From Saida S1
    Inner Join cadcli CLI on(S1.codcli = CLI.codigo)
    Where (S1.DataSaida >= '03/01/2012' AND S1.DataSaida <= '03/30/2012')
    Group By S1.codcli, Cli.rsocial
    Order By ValorTotalCliente Desc


    CODCLI    RSOCIAL     VALOR_TOTAL_DO_CLIENTE       PERCENT            VL_TOTAL_GERAL
    000330    CLIENTE A                               35.326,80              2,18                  1.623.611,02
    000392    CLIENTE B                                 9.651,90              0,59                  1.623.611,02
    001063    CLIENTE C                                 8.250,41              0,51                  1.623.611,02

    A coluna "VL_TOTAL_GERAL" nao precisa aparecer, só coloquei para mostrar que o valor é igual para todos os clientes

    Estou querendo aprender melhor CTEs, existe alguma alternativa usando CTEs ?

    Preciso executar esta consulta no MSSQL 2008 e Firebird 2.1

    Obrigado

    Zagatti, Angelo Itápolis-SP

    sexta-feira, 30 de março de 2012 17:09

Respostas

  • Bom dia Angelo,

    Neste caso não seria possivel jogar o valor total em uma variavel e depois fazer o select a partir desta variavel?

    Veja o exemplo abaixo:

    DECLARE @TABLE AS TABLE (
    COLUNA	INT,
    SOMA	DECIMAL(15,2));
    
    INSERT INTO @TABLE VALUES(1,15.2);
    INSERT INTO @TABLE VALUES(2,15.2);
    INSERT INTO @TABLE VALUES(2,15.2);
    INSERT INTO @TABLE VALUES(3,15.2);
    INSERT INTO @TABLE VALUES(3,15.2);
    INSERT INTO @TABLE VALUES(3,15.2);
    
    DECLARE @TOTAL DECIMAL(15,2);
    
    SET  @TOTAL =  (SELECT SUM(SOMA) FROM @TABLE);
    
    SELECT SUM(SOMA), @TOTAL AS TOTAL FROM @TABLE
    GROUP BY COLUNA

    Abçs,

    Adriano

    • Sugerido como Resposta Heloisa Pires segunda-feira, 9 de abril de 2012 20:01
    • Marcado como Resposta Angelo Zagatti segunda-feira, 9 de abril de 2012 22:15
    segunda-feira, 9 de abril de 2012 11:00

Todas as Respostas

  • Boa tarde Angelo,

    Não sei se usando CTE a questão de performance melhoraria 100%, acho melhor tentar 1º ver se as consultas estão retornando uma quantidade de registros em um tempo considerado bom.

    A 1º coisa para se ver é quem esta demorando mais, com os selects separados.

    -- 1º Select 
    Select S1.codcli,
           Cli.rsocial,
           SUM(S1.vltotal) VALOR_TOTAL_DO_CLIENTE
    From Saida S1       
     Inner Join cadcli CLI
        on (S1.codcli = CLI.codigo)
     Where (S1.DataSaida >= '03/01/2012' AND S1.DataSaida <= '03/30/2012')
     Group By S1.codcli, Cli.rsocial
     Order By ValorTotalCliente Desc
    
    -- 2º Select
    Select SUM(S3.vltotal) VlTotal
      From saida S3
     Where (S3.DataSaida >= '03/01/2012' AND S3.DataSaida <= '03/30/2012');
    

    Depois veja se há indices nas tabelas envolvidas (saida e cadcli ).

    Abçs,

    Adriano Nascimento

    sexta-feira, 30 de março de 2012 20:37
  • Adriano, obrigado pela ajuda.

    Seguinte:

    O 2º Select retorna o valor fixo de: 1623611.02 (este 2º Select e bem rapido- 1s)

    O 1º Select me retorna 2971 registros (clientes) - (Tambem é bastante rapido +/- 3s).

    Quando eu junto os dois, ai é que demora bastante pois, para cada um dos 2971 registros é executado o 2º select.

    O 2º Select tem que retornar sempres o mesmo valor. Simulando a substituiçao do 2º select pelo valor obtido do mesmo, tenho um select bastante rapido.

    Select S1.codcli,
           Cli.rsocial,
           SUM(S1.vltotal) VALOR_TOTAL_DO_CLIENTE
           ,ROUND((SUM(S1.vltotal) * 100.00 / ( 1623611.02
                                               -- 2ª Select
                                               --Select SUM(S2.vltotal) VlTotal
                                               --From saidaitem S2
                                               --Where (S2.DataSaida >= '03/01/2012' AND S2.DataSaida <= '03/30/2012')
                                               ) ),2) Percent
    From saidaitem S1
     Inner Join cadcli CLI
        on (S1.codcli = CLI.codigo)
     Where (S1.DataSaida >= '03/01/2012' AND S1.DataSaida <= '03/30/2012')
     Group By S1.codcli, Cli.rsocial
     Order By VALOR_TOTAL_DO_CLIENTE Desc

    Eu preciso que o 2º select, seja executado apenas uma vez, e o valor obtido seja usado no 1º select para cada um dos registros.

    Abraços,


    Zagatti, Angelo Itápolis-SP

    domingo, 1 de abril de 2012 13:19
  • Bom dia Angelo,

    Neste caso não seria possivel jogar o valor total em uma variavel e depois fazer o select a partir desta variavel?

    Veja o exemplo abaixo:

    DECLARE @TABLE AS TABLE (
    COLUNA	INT,
    SOMA	DECIMAL(15,2));
    
    INSERT INTO @TABLE VALUES(1,15.2);
    INSERT INTO @TABLE VALUES(2,15.2);
    INSERT INTO @TABLE VALUES(2,15.2);
    INSERT INTO @TABLE VALUES(3,15.2);
    INSERT INTO @TABLE VALUES(3,15.2);
    INSERT INTO @TABLE VALUES(3,15.2);
    
    DECLARE @TOTAL DECIMAL(15,2);
    
    SET  @TOTAL =  (SELECT SUM(SOMA) FROM @TABLE);
    
    SELECT SUM(SOMA), @TOTAL AS TOTAL FROM @TABLE
    GROUP BY COLUNA

    Abçs,

    Adriano

    • Sugerido como Resposta Heloisa Pires segunda-feira, 9 de abril de 2012 20:01
    • Marcado como Resposta Angelo Zagatti segunda-feira, 9 de abril de 2012 22:15
    segunda-feira, 9 de abril de 2012 11:00
  • Olá Adriano,

    Obrigado pela ajuda.

    Funcionou perfeitamente para MS SQL , porem preciso fazer a mesma coisa para firebird 2.1.

    Se voce souber alguma alternativa para firebird, eu agradeço.

    Abraços amigo, valeu mesmo.


    Zagatti, Angelo Itápolis-SP

    segunda-feira, 9 de abril de 2012 22:19