Separar campos quando utilizar UNION no FIREBIRD
Estou utilizando o FireBird 2.5 e preciso de ajuda, eu tenho que construir uma consulta SQL para retornar o total de "Contas a Receber" e o total de "Contas a Pagar" em aberto do banco de dados, totalizar por mês independente do período exibindo
saldo por mês e totais ao final do resultado. Tentei utilizar o "Union" e ele me deu os dados certos. porém não estou conseguindo separar as colunas
ai ele está me devolvendo da seguinte maneira:
Mês Total a Receber
Abril 9.121,63
Agosto 12.975,03
Dezembro 13.521,29
Dezembro 47112,38
Fevereiro 143646,86
Fevereiro 198236,3
Janeiro 69601,48
Janeiro 116815,26
Julho 11001,71
Junho 11687,77
Maio 8548,66
Março 98584,61
Março 149984,69
Novembro 12158,52
Novembro 29484,31
Outubro 73015,03
Setembro 2987,66
Setembro 11862
saldo por mês e totais ao final do resultado. Tentei utilizar o "Union" e ele me deu os dados certos. porém não estou conseguindo separar as colunas
select case extract (month from cr.data_emissao) when 1 then ''''''''Janeiro'''''''' when 2 then ''''''''Fevereiro'''''''' when 3 then ''''''''Março'''''''' when 4 then ''''''''Abril'''''''' when 5 then ''''''''Maio'''''''' when 6 then ''''''''Junho'''''''' when 7 then ''''''''Julho'''''''' when 8 then ''''''''Agosto'''''''' when 9 then ''''''''Setembro'''''''' when 10 then ''''''''Outubro'''''''' when 11 then ''''''''Novembro'''''''' when 12 then ''''''''Dezembro'''''''' end "Mês", sum(cr.valor_aberto)"Total a Receber" from contas_receber cr where cr.status = ''''''''A'''''''' group by extract (month from cr.data_emissao) union select case extract (month from cp.data_emissao) when 1 then ''''''''Janeiro'''''''' when 2 then ''''''''Fevereiro'''''''' when 3 then ''''''''Março'''''''' when 4 then ''''''''Abril'''''''' when 5 then ''''''''Maio'''''''' when 6 then ''''''''Junho'''''''' when 7 then ''''''''Julho'''''''' when 8 then ''''''''Agosto'''''''' when 9 then ''''''''Setembro'''''''' when 10 then ''''''''Outubro'''''''' when 11 then ''''''''Novembro'''''''' when 12 then ''''''''Dezembro'''''''' end, sum(cp.valor_aberto)"Total a Pagar" from contas_pagar cp where cp.status = ''''''''A'''''''' group by extract (month from cp.data_emissao)
ai ele está me devolvendo da seguinte maneira:
Mês Total a Receber
Abril 9.121,63
Agosto 12.975,03
Dezembro 13.521,29
Dezembro 47112,38
Fevereiro 143646,86
Fevereiro 198236,3
Janeiro 69601,48
Janeiro 116815,26
Julho 11001,71
Junho 11687,77
Maio 8548,66
Março 98584,61
Março 149984,69
Novembro 12158,52
Novembro 29484,31
Outubro 73015,03
Setembro 2987,66
Setembro 11862
Renato Akira
Curtidas 0
Respostas
Emerson Nascimento
29/06/2022
veja se isto atende
select 'RECEBER' Tipo, sum(case when extract(month from cr.data_emissao) = 1 then cr.valor_aberto else 0 end) Janeiro, sum(case when extract(month from cr.data_emissao) = 2 then cr.valor_aberto else 0 end) Fevereiro, sum(case when extract(month from cr.data_emissao) = 3 then cr.valor_aberto else 0 end) Marco, sum(case when extract(month from cr.data_emissao) = 4 then cr.valor_aberto else 0 end) Abril, sum(case when extract(month from cr.data_emissao) = 5 then cr.valor_aberto else 0 end) Maio, sum(case when extract(month from cr.data_emissao) = 6 then cr.valor_aberto else 0 end) Junho, sum(case when extract(month from cr.data_emissao) = 7 then cr.valor_aberto else 0 end) Julho, sum(case when extract(month from cr.data_emissao) = 8 then cr.valor_aberto else 0 end) Agosto, sum(case when extract(month from cr.data_emissao) = 9 then cr.valor_aberto else 0 end) Setembro, sum(case when extract(month from cr.data_emissao) = 10 then cr.valor_aberto else 0 end) Outubro, sum(case when extract(month from cr.data_emissao) = 11 then cr.valor_aberto else 0 end) Novembro, sum(case when extract(month from cr.data_emissao) = 12 then cr.valor_aberto else 0 end) Dezembro from contas_receber cr where cr.status = 'A' union select 'PAGAR' Tipo, sum(case when extract(month from cp.data_emissao) = 1 then cp.valor_aberto else 0 end) Janeiro, sum(case when extract(month from cp.data_emissao) = 2 then cp.valor_aberto else 0 end) Fevereiro, sum(case when extract(month from cp.data_emissao) = 3 then cp.valor_aberto else 0 end) Marco, sum(case when extract(month from cp.data_emissao) = 4 then cp.valor_aberto else 0 end) Abril, sum(case when extract(month from cp.data_emissao) = 5 then cp.valor_aberto else 0 end) Maio, sum(case when extract(month from cp.data_emissao) = 6 then cp.valor_aberto else 0 end) Junho, sum(case when extract(month from cp.data_emissao) = 7 then cp.valor_aberto else 0 end) Julho, sum(case when extract(month from cp.data_emissao) = 8 then cp.valor_aberto else 0 end) Agosto, sum(case when extract(month from cp.data_emissao) = 9 then cp.valor_aberto else 0 end) Setembro, sum(case when extract(month from cp.data_emissao) = 10 then cp.valor_aberto else 0 end) Outubro, sum(case when extract(month from cp.data_emissao) = 11 then cp.valor_aberto else 0 end) Novembro, sum(case when extract(month from cp.data_emissao) = 12 then cp.valor_aberto else 0 end) Dezembro from contas_pagar cp where cp.status = 'A'
GOSTEI 0
Renato Akira
29/06/2022
Então, isso é quase o resultado que tô precisando. Tem como fazer aparecer 3 colunas?
Meses | Valor a Receber | Valor a Pagar
GOSTEI 0
Renato Akira
29/06/2022
Então, isso é quase o resultado que tô precisando. Tem como fazer aparecer 3 colunas?
Meses | Valor a Receber | Valor a Pagar
Porque eu precisarei utilizar o execute blocks para retornar o resultado da seguinte forma:
https://prnt.sc/VsoCvnGFSkl1
GOSTEI 0
Emerson Nascimento
29/06/2022
em 3 colunas? claro!
select mes "Mês", sum(receber) "Total a Receber", sum(pagar) "Total a Pagar" from ( select case extract (month from cr.data_emissao) when 1 then 'Janeiro' when 2 then 'Fevereiro' when 3 then 'Março' when 4 then 'Abril' when 5 then 'Maio' when 6 then 'Junho' when 7 then 'Julho' when 8 then 'Agosto' when 9 then 'Setembro' when 10 then 'Outubro' when 11 then 'Novembro' when 12 then 'Dezembro' end mes, sum(cr.valor_aberto) receber, -- aqui acumula o valor a receber 0.0 pagar -- valor a pagar deve ser zero porque aqui usamos a tabela de contas a receber from contas_receber cr where cr.status = 'A' group by extract (month from cr.data_emissao) union select case extract (month from cp.data_emissao) when 1 then 'Janeiro' when 2 then 'Fevereiro' when 3 then 'Março' when 4 then 'Abril' when 5 then 'Maio' when 6 then 'Junho' when 7 then 'Julho' when 8 then 'Agosto' when 9 then 'Setembro' when 10 then 'Outubro' when 11 then 'Novembro' when 12 then 'Dezembro' end mes, 0.0 receber -- valor a receber deve ser zero porque aqui usamos a tabela de contas a pagar sum(cp.valor_aberto) pagar -- aqui acumula o valor a pagar from contas_pagar cp where cp.status = 'A' group by extract (month from cp.data_emissao) ) t group by t.mes
GOSTEI 0
Renato Akira
29/06/2022
Entendi como ficaria nesse caso, mas como ficaria se eu tivesse que trabalhar com execute blocks e colocar a ordem dos meses em ordem cronológica?
Para alcançar o seguinte resultado: https://prnt.sc/9Up1rQI2VdyD
Tentei fazer da seguinte forma, mas ainda estou travado com o problema das colunas.
Ai na consulta SQL ta me retornando dessa maneira: https://prnt.sc/Q2Tv28crThFT
Para alcançar o seguinte resultado: https://prnt.sc/9Up1rQI2VdyD
Tentei fazer da seguinte forma, mas ainda estou travado com o problema das colunas.
execute block returns ("Mês" varchar(15), r_valorCR numeric(15,2),r_valorCP numeric(15,2), r_saldo numeric (15,2)) as declare variable vRecebe numeric (15,2); declare variable vRecebido numeric (15,2); declare variable vPaga numeric(15,2); declare variable meses varchar(15); begin for select extract (month from cr.data_emissao),sum(cr.valor_aberto)vRecebe from contas_receber cr where cr.status = 'A' group by extract (month from cr.data_emissao) union all select extract (month from cp.data_emissao),sum(cp.valor_aberto)vPaga from contas_pagar cp where cp.status = 'A' group by extract (month from cp.data_emissao) into "Mês", r_valorCR do begin if ("Mês" = '1') then "Mês" = 'Janeiro'; if ("Mês" = '2') then "Mês" = 'Fevereiro'; if ("Mês" = '3') then "Mês" = 'Março'; if ("Mês" = '4') then "Mês" = 'Abril'; if ("Mês" = '5') then "Mês" = 'Maio'; if ("Mês" = '6') then "Mês" = 'Junho'; if ("Mês" = '7') then "Mês" = 'Julho'; if ("Mês" = '8') then "Mês" = 'Agosto'; if ("Mês" = '9') then "Mês" = 'Setembro'; if ("Mês" = '10') then "Mês" = 'Outubro'; if ("Mês" = '11') then "Mês" = 'Novembro'; if ("Mês" = '12') then "Mês" = 'Dezembro'; suspend; end end
Ai na consulta SQL ta me retornando dessa maneira: https://prnt.sc/Q2Tv28crThFT
GOSTEI 0
Renato Akira
29/06/2022
E preciso evitar o uso de subselect, utilizar apenas union all
GOSTEI 0
Emerson Nascimento
29/06/2022
evita-se o uso de subselects quando há muitos registros envolvidos.
no teu caso serão no máximo 24 registros (12 registros em cada seleção)
pra ordenar basta você incluir o mês propriamente dito:
no teu caso serão no máximo 24 registros (12 registros em cada seleção)
pra ordenar basta você incluir o mês propriamente dito:
select mes "Mês", sum(receber) "Total a Receber", sum(pagar) "Total a Pagar" from ( select extract (month from cr.data_emissao) ordem, case extract (month from cr.data_emissao) when 1 then 'Janeiro' when 2 then 'Fevereiro' when 3 then 'Março' when 4 then 'Abril' when 5 then 'Maio' when 6 then 'Junho' when 7 then 'Julho' when 8 then 'Agosto' when 9 then 'Setembro' when 10 then 'Outubro' when 11 then 'Novembro' when 12 then 'Dezembro' end mes, sum(cr.valor_aberto) receber, -- aqui acumula o valor a receber 0.0 pagar -- valor a pagar deve ser zero porque aqui usamos a tabela de contas a receber from contas_receber cr where cr.status = 'A' group by extract (month from cr.data_emissao) union select extract (month from cp.data_emissao) ordem, case extract (month from cp.data_emissao) when 1 then 'Janeiro' when 2 then 'Fevereiro' when 3 then 'Março' when 4 then 'Abril' when 5 then 'Maio' when 6 then 'Junho' when 7 then 'Julho' when 8 then 'Agosto' when 9 then 'Setembro' when 10 then 'Outubro' when 11 then 'Novembro' when 12 then 'Dezembro' end mes, 0.0 receber -- valor a receber deve ser zero porque aqui usamos a tabela de contas a pagar sum(cp.valor_aberto) pagar -- aqui acumula o valor a pagar from contas_pagar cp where cp.status = 'A' group by extract (month from cp.data_emissao) ) t group by t.ordem, t.mes order by t.ordem
GOSTEI 0
Renato Akira
29/06/2022
mas caso fosse necessário utilizar apenas o Union se o subselect, teria como representar ele no execute blocks ? Atualmente estou desenvolvendo dessa forma
execute block returns ("Mês" varchar(15), r_valorCR numeric(15,2),r_valorCP numeric(15,2), r_saldo numeric (15,2), r_tipo varchar(10)) as declare variable vRecebe numeric (15,2); declare variable vRecebido numeric (15,2); declare variable vPaga numeric(15,2); declare variable meses varchar(15); begin for select extract (month from cr.data_emissao), sum(cr.valor_aberto)vRecebe, 'CR'"TIPO" from contas_receber cr where cr.status = 'A' group by extract (month from cr.data_emissao) union all select extract (month from cp.data_emissao),sum(cp.valor_aberto)vPaga, 'CP'"TIPO" from contas_pagar cp where cp.status = 'A' group by extract (month from cp.data_emissao) order by 1 into "Mês", r_valorCR, r_tipo do begin if ("Mês" = '1') then "Mês" = 'Janeiro'; if ("Mês" = '2') then "Mês" = 'Fevereiro'; if ("Mês" = '3') then "Mês" = 'Março'; if ("Mês" = '4') then "Mês" = 'Abril'; if ("Mês" = '5') then "Mês" = 'Maio'; if ("Mês" = '6') then "Mês" = 'Junho'; if ("Mês" = '7') then "Mês" = 'Julho'; if ("Mês" = '8') then "Mês" = 'Agosto'; if ("Mês" = '9') then "Mês" = 'Setembro'; if ("Mês" = '10') then "Mês" = 'Outubro'; if ("Mês" = '11') then "Mês" = 'Novembro'; if ("Mês" = '12') then "Mês" = 'Dezembro'; suspend; end end
A consulta está retornando dessa forma: https://prnt.sc/Ncsy0DqXyxIs
GOSTEI 0
Renato Akira
29/06/2022
Outra dúvida, como eu faria para criar uma nova linha abaixo de tudo com nome "Totais" no lugar do nome do Mês e nos campos seguintes, a somatória de todos os meses e depois a diferença?
GOSTEI 0
Emerson Nascimento
29/06/2022
veja se assim funciona
execute block returns ("Mês" varchar(15), r_valorCR numeric(15,2), r_valorCP numeric(15,2), r_saldo numeric (15,2)) as declare numeromes int = 1; declare total_cr numeric(15,2) = 0; declare total_cp numeric(15,2) = 0; declare total_sld numeric(15,2) = 0; begin while (numeromes <= 12) do begin "Mês" = case numeromes when 01 then 'Janeiro' when 02 then 'Fevereiro' when 03 then 'Março' when 04 then 'Abril' when 05 then 'Maio' when 06 then 'Junho' when 07 then 'Julho' when 08 then 'Agosto' when 09 then 'Setembro' when 10 then 'Outubro' when 11 then 'Novembro' when 12 then 'Dezembro' end; -- estude a possibilidade de criar um campo pra guardar o mes -- e criar um indice por esse campo. -- assim a condicao seria "cr.status = 'A' and mes = :numeromes" -- desta forma de pesquisa seria mais rapida por que o indice -- seria usado na pesquisa (com o extract() nao ha uso de indice) select coalesce(sum(cr.valor_aberto),0) from contas_receber cr where cr.status = 'A' and extract(month from cr.data_emissao) = :numeromes into r_valorCR; -- estude a possibilidade de criar um campo pra guardar o mes -- e criar um indice por esse campo. -- assim a condicao seria "cp.status = 'A' and mes = :numeromes" -- desta forma de pesquisa seria muito mais rapida por que o indice -- seria usado na pesquisa (com o extract() nao ha uso de indice) select colaesce(sum(cp.valor_aberto),0) from contas_pagar cp where cp.status = 'A' and extract(month from cp.data_emissao) = :numeromes into r_valorCP; if (r_valorCR is null) then r_valorCR = 0; if (r_valorCP is null) then r_valorCP = 0; r_saldo := (r_valorCR - r_valorCP); -- totalizadores total_cr = total_cr + r_valorCR; total_cp = total_cp + r_valorCP; total_sld = total_sld + r_saldo; numeromes = numeromes + 1; suspend; end -- apresenta os totais "Mês" = 'Totais'; r_valorCR = total_cr; r_valorCP = total_cp; r_saldo = total_sld; suspend; end
GOSTEI 0