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.