Separar campos quando utilizar UNION no FIREBIRD

29/06/2022

0

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
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

Renato Akira

Responder

Posts

29/06/2022

Emerson Nascimento

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'

Responder

29/06/2022

Renato Akira


Então, isso é quase o resultado que tô precisando. Tem como fazer aparecer 3 colunas?
Meses | Valor a Receber | Valor a Pagar
Responder

29/06/2022

Renato Akira


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
Responder

30/06/2022

Emerson Nascimento

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
Responder

30/06/2022

Renato Akira

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.
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
Responder

30/06/2022

Renato Akira


E preciso evitar o uso de subselect, utilizar apenas union all
Responder

30/06/2022

Emerson Nascimento

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:
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

Responder

30/06/2022

Renato Akira

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
Responder

30/06/2022

Renato Akira

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?
Responder

30/06/2022

Emerson Nascimento

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
Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar