Select from Select no Firebird 2.5
Eu sei que em época onde os ORMs estão cada vez mais espertos, é natural que o número de programadores com habilidade de escrever um bom SQL acabe diminuindo.
Mas não se engane: bons programadores também precisam saber SQL – mesmo que seja pra ler o que o ORM montou e aferir se a estratégia adotada foi a melhor.
Enfim, deixe-me ser mais objetivo.
Eu estava escrevendo um SQL no qual a minha fonte de dados provinha de duas tabelas distintas. Pra piorar a minha situação, eu precisava que os dados fossem apresentados sem repetição e ordenados.
Se eu fosse apurar cada tabela eu teria algo mais ou menos assim:
# Dados da tabela de vendas
select distinct
produtos.codigo,
produtos.nome
from
vendas_itens
join
produtos
on
produtos.codigo = vendas_itens.produto
order by
produtos.codigo
produtos.nome
# Dados da tabela de doacoes
select distinct
produtos.codigo,
produtos.nome
from
doacoes_itens
join
produtos
on
produtos.codigo = doacoes_itens.produto
order by
produtos.codigo
produtos.nome
Eu não queria gerar uma coleção e fazer isso tudo na unha. Eu queria mesmo era pegar isso tudo diretamente num único resultset. E agora?
Felizmente o Firebird 2.5 introduziu a possibilidade de fazer Select from Select. Isso é genial para o nosso caso, pois podemos fazer algo assim:
select distinct
produtos.codigo,
produtos.nome
from
(
select distinct
vendas_itens.produto
from
vendas_itens
union all
select distinct
doacoes_itens.produto
from
doacoes_itens
) dados
join
produtos
on
produtos.codigo = dados.produto
order by
produtos.codigo,
produtos.nome
Lindo! Agora temos a lista dos produtos vindos de duas fontes de dados, sem repetição e ordenados.
Este truque pode ser usado para as agragações e outras funções. Se você tentar usar um group by
com um sum
e um union all
… não rola. Você terá que apelar pra técnica abaixo.
select
produtos.codigo,
produtos.nome
sum(dados.quantidade)
from
(
select
vendas_itens.produto,
sum(vendas_itens.quantidade)
from
vendas_itens
group by
vendas_itens.produto
union all
select
doacoes_itens.produto,
sum(doacoes_itens.quantidade)
from
doacoes_itens
group by
doacoes_itens.produto
) dados
join
produtos
on
produtos.codigo = dados.produto
group by
produtos.codigo,
produtos.nome
order by
produtos.codigo,
produtos.nome
É isso aí! Espero que essa dica lhe ajude.