- Este tópico contém 58 respostas, 4 vozes e foi atualizado pela última vez 15 anos, 9 meses atrás por
MARCIO_LOK.
-
AutorPosts
-
1 de junho de 2010 às 10:25 pm #94361
MARCIO_LOK
ParticipanteBoa tarde amigos
To tentando fazer uma funcao aonde pegue os debitos e creditos dos meses ….e acumule me me retorne o total, o problema é que nao esta acumulando, ele está trazendo o saldo final, ou seja, se eu escolher 3 meses, ele tras o saldo dos tres meses, eu queria que ele trouxesse o saldo de janeiro+fevereiro+marco por exemplo, segue o codigo, se alguem puder analisar pra mim agradeço muito:
create or replace function soma(mes in date, mes2 IN VARCHAR2, Valor IN NUMBER, Conta IN VARCHAR2, Conta2 IN VARCHAR2, num IN VARCHAR2)
return NUMBER
is
v_string_retorno NUMBER(15,2);
v_credito NUMBER(15,2); v_debito NUMBER(15,2); ano_deb NUMBER(15,2); ano_cred NUMBER(15,2); total NUMBER(15,2);
i INT;
BEGIN
v_string_retorno := 0; v_credito := 0; v_debito:=0; ano_deb:=0; ano_cred:=0;
–i:=1;
FOR i IN 1..mes2 LOOP
–WHILE i <= mes2 Loop IF To_Char(mes,'mm') <= i AND To_Char(mes,'yy') = '10' AND SubStr(Conta,1,11) = num THEN v_Credito := v_Credito+valor; ELSIF To_Char(mes,'mm') <= i AND To_Char(mes,'yy') = '10' AND SubStr(Conta2,1,11) = num THEN v_Debito := v_Debito+valor; END IF; ano_cred:=(ano_cred+v_credito); ano_deb :=(ano_deb + v_debito); --i:=i+1; END LOOP; v_string_retorno:=(Ano_Cred-ano_deb); return (v_string_retorno); end;2 de junho de 2010 às 9:22 am #94367fsitja
ParticipanteOlá Marcio,
Acho que você já fez essa mesma pergunta várias vezes, sempre disfarçada de uma pergunta nova. O problema não é que as pessoas não saibam ou não queiram ajudar, é que você precisa facilitar para que nós possamos entender a lógica que você necessita.
Faça de conta que você não conhece nada sobre o seu problema atual e releia a questão. Você entenderia claramente aonde ela está querendo chegar?
Indo ao ponto, você precisa dar exemplo dos dados de entrada (tabelas do seu sistema que estão envolvidas, e dados delas) e a forma que você espera enxergar os dados na saída. Um exemplo pequeno mas que sirva para que validemos a nossa proposta de solução de acordo com a lógica que você pediu.
Bom, juntando um pouco do que consegui entender, o problema no momento está sendo acumular valores ao longo dos meses.
A função SUM faz somatório com acumulação incrementando, segue um exemplo:
SQL> create table clanca (conta number(10),
2 data_lanc date,
3 credito number(10, 2),
4 debito number(10, 2),
5 valor number(10, 2));Table created
SQL> begin
2 insert into clanca (conta, data_lanc, credito, debito, valor)
3 values (100, to_date('05/01/2010', 'DD/MM/YYYY'), 1, null, 2000);
4 insert into clanca (conta, data_lanc, credito, debito, valor)
5 values (100, to_date('08/01/2010', 'DD/MM/YYYY'), null, 1, 500);
6 insert into clanca (conta, data_lanc, credito, debito, valor)
7 values (100, to_date('01/02/2010', 'DD/MM/YYYY'), 1, null, 2000);
8 insert into clanca (conta, data_lanc, credito, debito, valor)
9 values (100, to_date('02/02/2010', 'DD/MM/YYYY'), null, 1, 500);
10 insert into clanca (conta, data_lanc, credito, debito, valor)
11 values (100, to_date('20/03/2010', 'DD/MM/YYYY'), null, 1, 500);
12 insert into clanca (conta, data_lanc, credito, debito, valor)
13 values (200, to_date('25/01/2010', 'DD/MM/YYYY'), 1, null, 2000);
14 insert into clanca (conta, data_lanc, credito, debito, valor)
15 values (200, to_date('01/02/2010', 'DD/MM/YYYY'), null, 1, 500);
16 insert into clanca (conta, data_lanc, credito, debito, valor)
17 values (200, to_date('01/02/2010', 'DD/MM/YYYY'), 1, null, 2000);
18 insert into clanca (conta, data_lanc, credito, debito, valor)
19 values (200, to_date('01/03/2010', 'DD/MM/YYYY'), null, 1, 500);
20 insert into clanca (conta, data_lanc, credito, debito, valor)
21 values (200, to_date('20/04/2010', 'DD/MM/YYYY'), null, 1, 500);
22 commit;
23 end;
24 /PL/SQL procedure successfully completed
SQL> select conta,
2 ano,
3 mes,
4 movim_liquido_mes,
5 valor_acumulado_ano
6 from (select conta,
7 to_char(data_lanc, 'YYYY') ano,
8 to_char(data_lanc, 'MM') mes,
9 sum(case when debito is not null then valor * -1
10 when credito is not null then valor end) movim_liquido_mes,
11 sum(sum(case when debito is not null then valor * -1
12 when credito is not null then valor end))
13 over (partition by conta, to_char(data_lanc, 'YYYY') order by to_char(data_lanc, 'MM') asc) valor_acumulado_ano
14 from clanca
15 group by conta, to_char(data_lanc, 'MM'), to_char(data_lanc, 'YYYY'));CONTA ANO MES MOVIM_LIQUIDO_MES VALOR_ACUMULADO_ANO
100 2010 01 1500 1500 100 2010 02 1500 3000 100 2010 03 -500 2500 200 2010 01 2000 2000 200 2010 02 1500 3500 200 2010 03 -500 3000 200 2010 04 -500 25007 rows selected
SQL>
A documentação Oracle tem mais detalhes, se você quiser ler fica na url abaixo:
http://download.oracle.com/docs/cd/E118 … ons004.htm2 de junho de 2010 às 4:40 pm #94368MARCIO_LOK
ParticipanteBom primeiramente, obrigado por ajudar…
Minha intenção nunca foi fazer perguntas “disfarçadas” pelo contrário, estou fazendo algo um pouco diferente, e agora tenho pelo menos uma função….
outra coisa também, eu jamais disse que as pessoas nao tão querendo me ajudar, pelo contrario, esse Forum, tem sido de grande ajuda…. tenho aprendido mais com os amigos aqui do que em qualquer curso…
SEguindo seu exemplo, elaborei um exemplo do que estou tentando fazer, segue:SQL> create table clanca (
2 data date,
3 credito varchar2(11),
4 debito varchar2(11),
5 valor number(10,2));SQL> create table cConta (Codconta varchar2(11);
2 descricao varchar2(40);SQL> create table Saldo (Codconta varchar2(11);
2 descricao varchar2(40);
dez number(10,2);Ligacoes: A coluna Debito ou credito da tabela cLanca liga com a Coluna CodConta da tabela cConta e Saldo.
–Insert cLanca
insert into clanca (data, credito, debito, valor)
values (to_date(’05/01/2010′, ‘DD/MM/YYYY’), 12345678909, null, 2000);
insert into clanca (data, credito, debito, valor)
values (to_date(’06/01/2010′, ‘DD/MM/YYYY’), 12345678909, null, 4034);
insert into clanca (data, credito, debito, valor)
values (to_date(’05/01/2010′, ‘DD/MM/YYYY’), 12345678909, null, 2066);
insert into clanca (data, credito, debito, valor)
values (to_date(’06/01/2010′, ‘DD/MM/YYYY’), 12345678909, null, 4450);
insert into clanca (data, credito, debito, valor)
values (to_date(’10/01/2010′, ‘DD/MM/YYYY’), 12345678911, null, 2000);
insert into clanca (data, credito, debito, valor)
values (to_date(’23/01/2010′, ‘DD/MM/YYYY’), 12345678911, null, 4000);–Insert Saldo
insert into Saldo (CodConta, dez)
values (‘12345678909’,234.77);
insert into Saldo (CodConta, dez)
values (‘12345678911’,500);Correto?
O script que estou utilizando é este aqui:
Select
c.codConta As CODCONTAS,C.Descricao As DESCRICAO , (CASE WHEN length(c.codConta) = 01 THEN (Sum(case when To_Char(L.Data, 'mm') = '01' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = '01' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Credito THEN L.Valor end)+Nvl(O.dez,0))END) Janeiro , (CASE WHEN &mes >= 02 THEN (Sum(case when To_Char(L.Data, 'mm') <= '02' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 03 THEN (Sum(case when To_Char(L.Data, 'mm') <= '03' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 04 THEN (Sum(case when To_Char(L.Data, 'mm') <= '04' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 05 THEN (Sum(case when To_Char(L.Data, 'mm') <= '05' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 06 THEN (Sum(case when To_Char(L.Data, 'mm') <= '06' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 07 THEN (Sum(case when To_Char(L.Data, 'mm') <= '07' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 08 THEN (Sum(case when To_Char(L.Data, 'mm') <= '08' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 09 THEN (Sum(case when To_Char(L.Data, 'mm') <= '09' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 10 THEN (Sum(case when To_Char(L.Data, 'mm') <= '10' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 11 THEN (Sum(case when To_Char(L.Data, 'mm') <= '11' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') = 12 THEN (Sum(case when To_Char(L.Data, 'mm') <= '12' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Debito THEN -L.Valor when To_Char(L.Data, 'mm') <= '12' AND nvl(L.Valor,0) IS NOT NULL AND c.CodConta = L.Credito THEN L.Valor end)+Nvl(O.dez,0)) END) DezembroFrom cLanca L right join cConta C
ON L.CodColigada = C.CodColigada
AND (L.Credito = C.CodConta
OR L.Debito = C.CodConta)
AND To_Char(L.Data,'yy') = '10'
left join Saldo O
ON O.CodConta = C.CodConta
where
Substr(C.Codconta,1,1) = '1'GROUP BY C.CodConta,
C.Descricao, O.dezORDER BY C.codConta
Então o que eu to querendo fazer é, no final de tudo, depois dele apresentar o valor de todos os meses que eu quero… to querendo apresentar uma ultima coluna….. chamada total…
que é a soma dos meses por conta… exemplo:codConta Janeiro fevereiro total (Esta coluna tem que trazer o total dos meses que escolhi, conforme cada conta)
12345678911 345,88 45,88 391,76
12345678909 45,88 55,77 101,65
Obs: No exemplo a cima, escolhi 2 meses… caso estivesse escolhido 12 meses de 2009, me traria o valor dos 12 e a somatoria no final….Depois preciso somar tambem, todas as contas que comecem com ‘1’ (substr(c.CodConta,1,1) = ‘1’))….
Se puder me ajudar, vou trabalhando em cima do seu exemplo, vamos ver se consigo desenvolver alguma coisa, obrigado mais uma vez.
Marcio
2 de junho de 2010 às 5:38 pm #94370MARCIO_LOK
ParticipanteEntao, no exemplo que voce deu…. o que eu preciso saber é….
retornar apenas o valor…..
somar por contas…
conta valor
100 2500 (total dos 3 meses por exemplo)
200 2500CONTA ANO MES MOVIM_LIQUIDO_MES VALOR_ACUM_ANO
100 2010 01 1500 1500 100 2010 02 1500 3000 100 2010 03 -500 2500 200 2010 01 2000 2000 200 2010 02 1500 3500 200 2010 03 -500 3000 200 2010 04 -500 25007 rows selected
SQL>
valeu2 de junho de 2010 às 7:03 pm #94374fsitja
ParticipanteOpa, beleza Marcio,
Então, mas como vai ser feita a consulta? Se o Mês for passado para o SQL daria para colocar o que postei antes no from (ou numa view) e selecionar apenas a linha do mês desejado. Exemplo:
SQL> select conta, ano, mes, valor_acumulado_ano
2 from
3 (
4 select conta,
5 ano,
6 mes,
7 movim_liquido_mes,
8 valor_acumulado_ano
9 from (select conta,
10 to_char(data_lanc, 'YYYY') ano,
11 to_char(data_lanc, 'MM') mes,
12 sum(case when debito is not null then valor * -1
13 when credito is not null then valor end) movim_liquido_mes,
14 sum(sum(case when debito is not null then valor * -1
15 when credito is not null then valor end))
16 over (partition by conta, to_char(data_lanc, 'YYYY') order by to_char(data_lanc, 'MM') asc) valor_acumulado_ano
17 from clanca
18 group by conta, to_char(data_lanc, 'MM'), to_char(data_lanc, 'YYYY'))
19 ) where mes = 3;CONTA ANO MES VALOR_ACUMULADO_ANO
100 2010 03 2500 200 2010 03 3000Ou colocando numa view:
SQL> create or replace view vw_movimento_mensal as
2 select conta,
3 ano,
4 mes,
5 movim_liquido_mes,
6 valor_acumulado_ano
7 from (select conta,
8 to_char(data_lanc, 'YYYY') ano,
9 to_char(data_lanc, 'MM') mes,
10 sum(case when debito is not null then valor * -1
11 when credito is not null then valor end) movim_liquido_mes,
12 sum(sum(case when debito is not null then valor * -1
13 when credito is not null then valor end))
14 over (partition by conta, to_char(data_lanc, 'YYYY') order by to_char(data_lanc, 'MM') asc) valor_acumulado_ano
15 from clanca
16 group by conta, to_char(data_lanc, 'MM'), to_char(data_lanc, 'YYYY'));View created
SQL> select * from vw_movimento_mensal where mes = 3;
CONTA ANO MES MOVIM_LIQUIDO_MES VALOR_ACUMULADO_ANO
100 2010 03 -500 2500 200 2010 03 -500 3000SQL>
Como o mês de abril continha um lançamento também, ele não aparece nessa consulta no saldo de março ainda.
2 de junho de 2010 às 7:12 pm #94376MARCIO_LOK
ParticipanteHum, assim deu certo.
Da pra pegar o total…Um ultimo problema que nao consegui resolver é:
Nesse script que te passei ele apresenta as contas assim:
Conta Descricao Janeiro fevereiro….até dezembro
1 Ativo
12 Circulante
123 Aplicacoes
1234 Bancos
1234567899 Brasil 345.88 456.88
1234567888 Bradesco 6567.99 6789.99Entao, eu preciso somar na frente do Ativo todos os codigos da conta que comecam com 1….
Somar no circulante todos as contas que comecam com 12….
Somar na frente da aplicacoes todos as contas que comecam 123..
assim por diante… pegar mes a mes…no script que eu fiz, só tenho valores (cconta) nos codigos com 11 caracteres, precisava somar eles na frente do ativo…
Caso vc nao possa me ajudar, vou postar como um novo topico, e encerrar esse, que voce ja me ajudou muito…
Valeu2 de junho de 2010 às 9:55 pm #94379fsitja
ParticipanteUmm… não entendi muito bem. “Ativo”, “Circulante”, “Aplicacoes” e “Banco” etc são tipo uma hierarquia, onde cada algarismo que compõe o número da conta define qual é?
Tipo, Conta que comece com 1 é Ativo, Conta que comece por 2 é passivo e assim por diante? Se for assim onde fica essa hierarquia, onde a gente pega a descrição “Ativo”, “Circulante”, etc? A hierarquia fica na mesma tabela CCONTA onde ficam as contas que possuem saldo, no problema anterior?
O que você quer é assim?
Conta Desc JAN ... DEZ TOTAL
1 ATIVO 1000 3000 25000
1.1 CIRCULANTE 300 2000 15000
1.2 NÃO CIRCULANTE 700 1000 10000
Totalizando no nível superior o quanto tem nos níveis de baixo?Se for, esclarece por gentileza se a tabela de contas é uma só, e se pode haver débitos e créditos apenas em nós do último nível (folhas).
A consulta sempre será filtrada para um único ano do calendário?
2 de junho de 2010 às 10:04 pm #94380MARCIO_LOK
ParticipanteIsso… exatamente….
Vou responder suas perguntas:(negrito)
Umm… não entendi muito bem. “Ativo”, “Circulante”, “Aplicacoes” e “Banco” etc são tipo uma hierarquia, onde cada algarismo que compõe o número da conta define qual é?
Tabela: CCONTATipo, Conta que comece com 1 é Ativo, Conta que comece por 2 é passivo e assim por diante? Se for assim onde fica essa hierarquia, onde a gente pega a descrição “Ativo”, “Circulante”, etc? A hierarquia fica na mesma tabela CCONTA onde ficam as contas que possuem saldo, no problema anterior?
ExatamenteO que você quer é assim?
Código:Conta Desc JAN … DEZ TOTAL
1 ATIVO 1000 3000 25000
1.1 CIRCULANTE 300 2000 15000
1.2 NÃO CIRCULANTE 700 1000 10000
ExatamenteTotalizando no nível superior o quanto tem nos níveis de baixo?
ExatamenteSe for, esclarece por gentileza se a tabela de contas é uma só, e se pode haver débitos e créditos apenas em nós do último nível (folhas).
[b]A tabela de contas é uma só (CCONTAS)
Tabela de movimentacao (CLANCA)
pode haver debitos e creditos sim[/b]A consulta sempre será filtrada para um único ano do calendário?
Não, eu terei que entrar para o cliente.Valeu
2 de junho de 2010 às 10:09 pm #94381MARCIO_LOK
ParticipanteSó pra completar a resposta do email a cima…..
O script que postei acima…. faz todo esse procedimento, só nao totaliza nos niveis superiores…. deve ser porque usei right join em uma tabela, e left join na outra… valeu , brigadao
7 de junho de 2010 às 5:19 pm #94415MARCIO_LOK
ParticipanteAlguem pode me ajudar?[b][/b]
8 de junho de 2010 às 6:40 am #94440fsitja
ParticipanteMarcio,
Desculpe se é minha falha, mas eu estou tendo dificuldades para entender o layout do relatório.
O que você pediu inicialmente, para acumular os dados ao longo dos meses, é uma coisa incompatível com a subtotalização por nível de conta. Isso porque se for subtotalizar os acumulados vai dar todo o cálculo errado.
A função grouping sets pode ser usada para definir rollups e agrupamentos “customizados”, mas o que você está procurando é, essencialmente, um outro relatório, distinto do anterior.
— Para ilustrar:
No exemplo de script que você postou não existem os dados que você citou que quer enxergar, então não tem como testar. O script tem erros de sintaxe, logo nem roda. Quando for postar código, por favor, tente validar antes e no post use as tags de code entre colchetes para manter a formatação e ficar legível.
De toda forma, veja no exemplo que criei abaixo:
SQL> create table cconta (codconta varchar2(11) primary key,
2 descricao varchar2(40));Table created
SQL> create table clanca (conta varchar2(11) references cconta(codconta),
2 data_lanc date,
3 credito number(10, 2),
4 debito number(10, 2),
5 valor number(10, 2));Table created
SQL> begin
2 -- inserts de contas
3 insert into cconta (codconta, descricao) values (1, 'ATIVO');
4 insert into cconta (codconta, descricao) values (2, 'PASSIVO');
5 insert into cconta (codconta, descricao) values (11, 'CIRCULANTE');
6 insert into cconta (codconta, descricao) values (12, 'NÃO-CIRCULANTE');
7 insert into cconta (codconta, descricao) values (111, 'APLICAÇÕES');
8 -- inserts de lancamentos
9 insert into clanca (conta, data_lanc, credito, debito, valor)
10 values (11, to_date('05/01/2010', 'DD/MM/YYYY'), 1, null, 2000);
11 insert into clanca (conta, data_lanc, credito, debito, valor)
12 values (11, to_date('08/01/2010', 'DD/MM/YYYY'), null, 1, 500);
13 insert into clanca (conta, data_lanc, credito, debito, valor)
14 values (11, to_date('01/02/2010', 'DD/MM/YYYY'), 1, null, 2000);
15 insert into clanca (conta, data_lanc, credito, debito, valor)
16 values (11, to_date('02/02/2010', 'DD/MM/YYYY'), null, 1, 500);
17 insert into clanca (conta, data_lanc, credito, debito, valor)
18 values (11, to_date('20/03/2010', 'DD/MM/YYYY'), null, 1, 500);
19 insert into clanca (conta, data_lanc, credito, debito, valor)
20 values (111, to_date('10/02/2010', 'DD/MM/YYYY'), 1, null, 999);
21 insert into clanca (conta, data_lanc, credito, debito, valor)
22 values (12, to_date('25/01/2010', 'DD/MM/YYYY'), 1, null, 2000);
23 insert into clanca (conta, data_lanc, credito, debito, valor)
24 values (12, to_date('01/02/2010', 'DD/MM/YYYY'), null, 1, 500);
25 insert into clanca (conta, data_lanc, credito, debito, valor)
26 values (12, to_date('01/02/2010', 'DD/MM/YYYY'), 1, null, 2000);
27 insert into clanca (conta, data_lanc, credito, debito, valor)
28 values (12, to_date('01/03/2010', 'DD/MM/YYYY'), null, 1, 500);
29 insert into clanca (conta, data_lanc, credito, debito, valor)
30 values (12, to_date('20/04/2010', 'DD/MM/YYYY'), null, 1, 500);
31 commit;
32 end;
33 /PL/SQL procedure successfully completed
SQL>
SQL> select codconta,
2 nivel1,
3 nivel2,
4 ano,
5 mes,
6 movim_liquido_mes,
7 valor_acumulado_ano
8 from (select c.codconta,
9 substr(c.codconta, 1, 1) nivel1,
10 substr(c.codconta, 1, 2) nivel2,
11 to_char(data_lanc, 'YYYY') ano,
12 to_char(data_lanc, 'MM') mes,
13 sum(case when debito is not null then valor * -1
14 when credito is not null then valor end) movim_liquido_mes,
15 sum(sum(case when debito is not null then valor * -1
16 when credito is not null then valor end))
17 over (partition by c.codconta, to_char(data_lanc, 'YYYY') order by to_char(data_lanc, 'MM') asc) valor_acumulado_ano
18 from (select rpad(codconta, 11, '0') codconta, descricao from cconta) c
19 left join (select rpad(conta, 11, '0') codconta, l.* from clanca l) l on l.codconta = c.codconta
20 group by
21 grouping sets (
22 (c.codconta, to_char(data_lanc, 'MM'), to_char(data_lanc, 'YYYY')),
23 rollup(substr(c.codconta, 1, 1)),
24 rollup(substr(c.codconta, 1, 2))
25 ));CODCONTA NIVEL1 NIVEL2 ANO MES MOVIM_LIQUIDO_MES VALOR_ACUMULADO_ANO
10000000000
11000000000 2010 01 1500 1500
11000000000 2010 02 1500 3000
11000000000 2010 03 -500 2500
11100000000 2010 02 999 999
12000000000 2010 01 2000 2000
12000000000 2010 02 1500 3500
12000000000 2010 03 -500 3000
12000000000 2010 04 -500 2500
20000000000
20 23996
10 23996
5999 23996
12 2500 23996
11 3499 23996
1 5999 23996
5999 23996
2 2399618 rows selected
SQL>
A coluna de acumulado mostra uma totalização do acumulado anteriormente, o que dá um resultado maluco que não é correto (23.996).
Outra coisa: o seu modelo de dados está bastante confuso, com as contas de vários níveis dentro da mesma tabela, sem relacionamentos nem restrições de integridade (FKs). Mesmo para poder fazer a subtotalização simples (sem a coluna de acumulado), seria necessário saber de antemão o número de níveis da hierarquia.
8 de junho de 2010 às 5:29 pm #94445MARCIO_LOK
ParticipanteO que eu to querendo é apenas somar as contas….e subcontas… apenas isso…
conta descricao janeiro fevereiro …ate dezembro
1 contaprincipal 6 7
12 segundaconta 6 7
123 terceiraconta 6 7
1234 quartaconta 6 7
12345 etc quintaconta1 1 5
12346 quintaconta2 2 1
12347 quintaconta3 3 1Obs: As Contas com o mesmo tamanho e que comecam com um (por exemplo) ele soma, como no caso 12345, 12346 e 12347 e ai somando em cima das contas que comecam com 1….. e assim com todas que comecam com dois…etc…
Parece que o caminho deve ser com esse grouping set, que eu nao tinha nem ouvido falar, vou pesquisar, se vc puder me ajudar, agradeco muito.
Marcio
9 de junho de 2010 às 6:33 am #94469fsitja
ParticipanteMarcio, fiz um exemplo simplificado, apenas para 3 meses (jan, fev e mar) e para uma hierarquia de contas com 3 níveis de profundidade. Porém para incrementar com mais níveis é bem simples, só evoluir conforme está abaixo.
No where é preciso selecionar apenas um único ano cada vez que executar o SQL. No exemplo coloquei ‘2010’.
A tabela de saldo eu não coloquei, mas já mostrei num outro tópico como que faz com ela.
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0
Connected as FSITJASQL>
SQL> create table cconta (codconta varchar2(11) primary key,
2 descricao varchar2(40));Table created
SQL> create table clanca (conta varchar2(11) references cconta(codconta),
2 data_lanc date,
3 credito number(10, 2),
4 debito number(10, 2),
5 valor number(10, 2));Table created
SQL> begin
2 -- inserts de contas
3 insert into cconta (codconta, descricao) values (1, '1.0.0');
4 insert into cconta (codconta, descricao) values (2, '2.0.0');
5 insert into cconta (codconta, descricao) values (11, '1.1.0');
6 insert into cconta (codconta, descricao) values (12, '1.2.0');
7 insert into cconta (codconta, descricao) values (111, '1.1.1');
8 insert into cconta (codconta, descricao) values (112, '1.1.2');
9 insert into cconta (codconta, descricao) values (21, '2.1.0');
10 insert into cconta (codconta, descricao) values (211, '2.1.1');
11 -- inserts de lancamentos
12 insert into clanca (conta, data_lanc, credito, debito, valor)
13 values (11, to_date('05/01/2010', 'DD/MM/YYYY'), 1, null, 20000);
14 insert into clanca (conta, data_lanc, credito, debito, valor)
15 values (11, to_date('08/01/2010', 'DD/MM/YYYY'), null, 1, 50000);
16 insert into clanca (conta, data_lanc, credito, debito, valor)
17 values (11, to_date('01/02/2010', 'DD/MM/YYYY'), 1, null, 80000);
18 insert into clanca (conta, data_lanc, credito, debito, valor)
19 values (11, to_date('02/02/2010', 'DD/MM/YYYY'), null, 1, 130000);
20 insert into clanca (conta, data_lanc, credito, debito, valor)
21 values (11, to_date('20/03/2010', 'DD/MM/YYYY'), null, 1, 40000);
22 insert into clanca (conta, data_lanc, credito, debito, valor)
23 values (111, to_date('10/02/2010', 'DD/MM/YYYY'), 1, null, 20000);
24 insert into clanca (conta, data_lanc, credito, debito, valor)
25 values (112, to_date('20/03/2010', 'DD/MM/YYYY'), null, 1, 10000);
26 insert into clanca (conta, data_lanc, credito, debito, valor)
27 values (12, to_date('25/01/2010', 'DD/MM/YYYY'), 1, null, 3000);
28 insert into clanca (conta, data_lanc, credito, debito, valor)
29 values (12, to_date('01/02/2010', 'DD/MM/YYYY'), null, 1, 1000);
30 insert into clanca (conta, data_lanc, credito, debito, valor)
31 values (12, to_date('01/02/2010', 'DD/MM/YYYY'), 1, null, 5000);
32 insert into clanca (conta, data_lanc, credito, debito, valor)
33 values (12, to_date('01/03/2010', 'DD/MM/YYYY'), null, 1, 7000);
34 insert into clanca (conta, data_lanc, credito, debito, valor)
35 values (12, to_date('20/03/2010', 'DD/MM/YYYY'), null, 1, 5000);
36 insert into clanca (conta, data_lanc, credito, debito, valor)
37 values (2, to_date('20/01/2010', 'DD/MM/YYYY'), 1, null, 100);
38 insert into clanca (conta, data_lanc, credito, debito, valor)
39 values (21, to_date('20/01/2010', 'DD/MM/YYYY'), 1, null, 200);
40 insert into clanca (conta, data_lanc, credito, debito, valor)
41 values (211, to_date('20/01/2010', 'DD/MM/YYYY'), 1, null, 300);
42 commit;
43 end;
44 /PL/SQL procedure successfully completed
SQL>
SQL> with mov_mensal as (
2 select codconta,
3 nivel1,
4 nivel2,
5 nivel3,
6 ano,
7 sum(case when mes = '01' then mov_liq_mes end) jan,
8 sum(case when mes = '02' then mov_liq_mes end) fev,
9 sum(case when mes = '03' then mov_liq_mes end) mar,
10 sum(mov_liq_mes) tot_ano
11 from (select c.codconta,
12 substr(c.codconta, 1, 1) nivel1,
13 substr(c.codconta, 1, 2) nivel2,
14 substr(c.codconta, 1, 3) nivel3,
15 to_char(data_lanc, 'YYYY') ano,
16 to_char(data_lanc, 'MM') mes,
17 sum(case when debito is not null then valor * -1
18 when credito is not null then valor end) mov_liq_mes
19 from (select rpad(codconta, 11, '0') codconta, descricao from cconta) c
20 left join (select rpad(conta, 11, '0') codconta, l.*
21 from clanca l
22 where to_char(l.data_lanc, 'YYYY') = '2010') l on l.codconta = c.codconta
23 group by c.codconta, to_char(data_lanc, 'MM'), to_char(data_lanc, 'YYYY'))
24 group by codconta, nivel1, nivel2, nivel3, ano)
25 -- end with
26 select c.descricao, t.*
27 from (select coalesce(nivel1, nivel2, nivel3) codconta,
28 sum(jan) jan,
29 sum(fev) fev,
30 sum(mar) mar,
31 sum(tot_ano) tot_ano
32 from mov_mensal
33 group by grouping sets ((nivel1), (nivel2), (nivel3))
34 having (substr(nivel1, length(nivel1), 1) != '0')
35 or (substr(nivel2, length(nivel2), 1) != '0')
36 or (substr(nivel3, length(nivel3), 1) != '0')) t
37 join cconta c on c.codconta = t.codconta
38 order by t.codconta;DESCRICAO CODCONTA JAN FEV MAR TOT_ANO
1.0.0 1 -27000 -26000 -62000 -115000
1.1.0 11 -30000 -30000 -50000 -110000
1.1.1 111 20000 20000
1.1.2 112 -10000 -10000
1.2.0 12 3000 4000 -12000 -5000
2.0.0 2 600 600
2.1.0 21 500 500
2.1.1 211 300 3008 rows selected
SQL>
9 de junho de 2010 às 6:14 pm #94475MARCIO_LOK
ParticipanteParabens, o que eu queria era exatamente isso desde o inicio,
outro ponto positivo é que o tempo de execução do script….o que eu estava tentando desenvolver demorava em media de 4 a cinco MINUTOS, o teu… leva 09 segundos em uma base enorme….. parabens mesmo, pela paciência… pelo seu nivel de conhecimento… fiz algumas adaptações, levarei um bom tempo pra entender o que se passa ali…
eu estava tentando usar funções, criar matriz bidimensional para guardar os codigos, etc….. vc conseguiu resolver tudo, num unico codigo, e em um tempo de execução incrivel.Só que alguns detalhes precisam ser feitos, acredito que agora seja bem simples pra voce…
1) eu quero que ele traga apenas todos os codigos que comecem com ‘3’ , seria apenas incluir um –and substr(c.codconta),1,1) = ‘3’ só nao sei aonde coloco isso, tentei em alguns selects e deu erro…. parece ser simples isso correto?
2) a tabela clanca… nao tem o campo CONTA, ai esta dando erro nesta expressao sua…
“….sum(case when debito is not null then valor * -1
when credito is not null then valor end) mov_liq_mes
from (select rpad(codconta, 11, ‘0’) codconta, descricao from cconta) c
left join (select rpad(conta, 11, ‘0’) codconta, l.*
from clanca l….Obs: Substitui por debito só para testar, porem acredito que precisaria vincula-la com o credito tambem, para que os valores batam correto?
Como poderia fazer isso?3) o numero maximo de contas que tenho hoje é 11 digitos…. preparei para 20 digitos…. funcionou perfeitamente… só que percebi que ele traz os valores das contas…. só nao tras das contas que que terminam…01 (onze digitos), exemplo:
311331123401 (termina com 01) essa ele nao tras o valor na frente…
311331123402 tras perfeitamente
311331123403 tras perfeitamenteSó nao tras mesmo as que teminam com 01…
4) ultima coisa:
Existem algumas contas que nao trazem valor nenhum no mes….exemplo:
conta jan fev marc …..
1122 0 0 0 nao mostrar essa conta,
567 0 345 0 mostrar essa…pq tem movimento..nao tras nenhum valor… eu queria que ele nao trouxesse, nao mostrasse as contas que nao tem valor…. se tiver valor em um dos meses pode trazer… nao é pra trazer se nao houver movimento no periodo… parece simples ne?
Brigadao… vou mexendo aqui pra ver se resolvo algo…
meu codigo adaptado ficou assim:
with mov_mensal as (
select codconta,
nivel1,
nivel2,
nivel3,
nivel4,
nivel5,
nivel6,
nivel7,
nivel8,
nivel9,
nivel10,
nivel11,
nivel12,
nivel13,
nivel14,
nivel15,
nivel16,
nivel17,
nivel18,
nivel19,
nivel20,
ano,
sum(case when mes = ’01’ then mov_liq_mes end) jan,
sum(case when mes = ’02’ then mov_liq_mes end) fev,
sum(case when mes = ’03’ then mov_liq_mes end) mar,
sum(case when mes = ’04’ then mov_liq_mes end) abr,
sum(case when mes = ’05’ then mov_liq_mes end) mai,
sum(case when mes = ’06’ then mov_liq_mes end) jun,
sum(case when mes = ’07’ then mov_liq_mes end) jul,
sum(case when mes = ’08’ then mov_liq_mes end) ago,
sum(case when mes = ’09’ then mov_liq_mes end) sete,
sum(case when mes = ’10’ then mov_liq_mes end) out,
sum(case when mes = ’11’ then mov_liq_mes end) nov,
sum(case when mes = ’12’ then mov_liq_mes end) dez,sum(mov_liq_mes) tot_ano from (select c.codconta, substr(c.codconta, 1, 1) nivel1, substr(c.codconta, 1, 2) nivel2, substr(c.codconta, 1, 3) nivel3, substr(c.codconta, 1, 4) nivel4, substr(c.codconta, 1, 5) nivel5, substr(c.codconta, 1, 6) nivel6, substr(c.codconta, 1, 7) nivel7, substr(c.codconta, 1, 8) nivel8, substr(c.codconta, 1, 9) nivel9, substr(c.codconta, 1,10) nivel10, substr(c.codconta, 1,11) nivel11, substr(c.codconta, 1,12) nivel12, substr(c.codconta, 1,13) nivel13, substr(c.codconta, 1,14) nivel14, substr(c.codconta, 1,15) nivel15, substr(c.codconta, 1,16) nivel16, substr(c.codconta, 1,17) nivel17, substr(c.codconta, 1,18) nivel18, substr(c.codconta, 1,19) nivel19, substr(c.codconta, 1,20) nivel20, to_char(data, 'YYYY') ano, to_char(data, 'MM') mes, sum(case when debito is not null then valor * -1 when credito is not null then valor end) mov_liq_mes from (select rpad(codconta, 11, '0') codconta, descricao from cconta) c left join (select rpad(debito, 11, '0') codconta, l.* from clanca l where to_char(l.data, 'YYYY') = '2010') l on l.codconta = c.codconta group by c.codconta, to_char(data, 'MM'), to_char(data, 'YYYY')) group by codconta, nivel1, nivel2, nivel3, nivel4, nivel5, nivel6, nivel7, nivel8, nivel9, nivel10, nivel11, nivel12, nivel13, nivel14, nivel15, nivel16, nivel17, nivel18, nivel19, nivel20, ano)— end with
select c.descricao, t.*
from (select DISTINCT coalesce(nivel1, nivel2, nivel3, nivel4 ,nivel5, nivel6, nivel7, nivel8, nivel9, nivel10, nivel11, nivel12, nivel13, nivel14, nivel15, nivel16, nivel17, nivel18, nivel19, nivel20) codconta,
sum(jan) jan,
sum(fev) fev,
sum(mar) mar,
sum(abr) abr,
sum(mai) mai,
sum(jun) jun,
sum(jul) jul,
sum(ago) ago,
sum(sete) sete,
sum(out) out,
sum(nov) nov,
sum(dez) dez,
sum(tot_ano) tot_ano,
Round(sum(tot_ano),2)/12 media
from mov_mensal
group by grouping sets ((nivel1), (nivel2), (nivel3), (nivel4), (nivel5), (nivel6), (nivel7), (nivel8), (nivel9), (nivel10), (nivel11), (nivel12), (nivel13), (nivel14), (nivel15), (nivel16), (nivel17), (nivel18), (nivel19), (nivel20))
having (substr(nivel1, length(nivel1), 1) != ‘0’)
or (substr(nivel2, length(nivel2), 1) != ‘0’)
or (substr(nivel3, length(nivel3), 1) != ‘0’)
or (substr(nivel4, length(nivel4), 1) != ‘0’)
or (substr(nivel5, length(nivel5), 1) != ‘0’)
or (substr(nivel6, length(nivel6), 1) != ‘0’)
or (substr(nivel7, length(nivel7), 1) != ‘0’)
or (substr(nivel8, length(nivel8), 1) != ‘0’)
or (substr(nivel9, length(nivel9), 1) != ‘0’)
or (substr(nivel10, length(nivel10), 1) != ‘0’)
or (substr(nivel11, length(nivel11), 1) != ‘0’)
or (substr(nivel12, length(nivel12), 1) != ‘0’)
or (substr(nivel13, length(nivel13), 1) != ‘0’)
or (substr(nivel14, length(nivel14), 1) != ‘0’)
or (substr(nivel15, length(nivel15), 1) != ‘0’)
or (substr(nivel16, length(nivel16), 1) != ‘0’)
or (substr(nivel17, length(nivel17), 1) != ‘0’)
or (substr(nivel18, length(nivel18), 1) != ‘0’)
or (substr(nivel19, length(nivel19), 1) != ‘0’)
or (substr(nivel20, length(nivel20), 1) != ‘0’)) tjoin cconta c on c.codconta = t.codcontaorder by t.codconta;
Obs: Mudei o nome do campo Data_Lanc, para Data….acrecentei 20 niveis…. embora só trabalhei com 11 no maximo, vou deixar pronto para crescer até 20……
Valeu… pela eficiencia do codigo, pela paciencia, e pela forca de vontade em ajudar…. ainda existe profissionais competentes como voce… prontos a ajudar os iniciantes… obrigado
9 de junho de 2010 às 7:43 pm #94480MARCIO_LOK
Participanteamigo, eu pedi para que você me ajudasse em quatro questoes…
uma delas conseguir resolver…. e outras consegui identificar…
Resolvida:
1) eu quero que ele traga apenas todos os codigos que comecem com ‘3’ , seria apenas incluir um –and substr(c.codconta),1,1) = ‘3’ só nao sei aonde coloco isso, tentei em alguns selects e deu erro…. parece ser simples isso correto?
Coloquei aqui, deu certo:
… from (select rpad(codconta, 20, ‘0’) codconta, descricao from cconta WHERE SubStr(codconta,1,1)=’3′) c…A que consegui identificar é a questao 2..
2) a tabela clanca… nao tem o campo CONTA, ai esta dando erro nesta expressao sua…
“….sum(case when debito is not null then valor * -1
when credito is not null then valor end) mov_liq_mes
from (select rpad(codconta, 11, ‘0’) codconta, descricao from cconta) c
left join (select rpad(conta, 11, ‘0’) codconta, l.*
from clanca l….
Conforme mencionado acima… o problema é no campo conta da clanca… eu nao tenho esse campo…. se eu substituir para debito da um valor… para credito da outro, acho que precisaria colocar os dois.. ou vincular…
acredito que resolvendo isso, a questao numero três tambem será resolvida, porque os codigos com final 001 nao aparecem porque o campo conta foi substituido por credito, quando substitui por debito apareceu, acredito que resolvendo um, resolverá o outro…estou tentando resolver a questao numero 4…
assim que possivel, me ajuda, obrigado -
AutorPosts
- Você deve fazer login para responder a este tópico.