Usuário com melhor resposta
Select ou CTE ajuda

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
ObrigadoZagatti, Angelo Itápolis-SP
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
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
-
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 DescEu 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
-
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
-
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