SQL: Diferenças entre UNION e UNION ALL

Compartilhe:

Artigo com o objetivo de esclarecer com exemplos práticos para melhorar a compreensão sobre quais são as Diferenças entre UNION e UNION ALL

Para compreender de forma básica tem a ver com linhas duplicadas. UNION combinará linhas das demais tabelas combinadas que já existam no resultado das consultas aplicadas nas tabelas anteriores; Já o UNION ALL não se importará com isso.

Uma outra alternativa de como ver UNION e UNION ALL vem diretamente da matemática:

  • UNION é uma operação de coleções de elementos que resulta em um terceiro conjunto;
  • UNION ALL é uma operação de coleções de elementos resultando em uma bag.

Aqui, tanto conjunto como bag são coleções de elementos. A diferença entre eles é dada pela “operação de soma” de elementos a uma coleção pré-existente. Vou definir como “soma”:

el + C = R

Onde el é um elemento qualquer, C é a coleção pré-existente e R é a coleção resultante da operação, que contém em sua totalidade C e também tem como elemento el.

Abre em nova aba

Se elnão existir previamente em C,então as operações com conjunto e bagsão idênticas. Agora,se eljá existir previamente em C,a soma com um conjunto resultará em R==C,não afetando o resultante. Porém a bagé alterada com a adição de el,portanto R !=C.

Curso Banco de Dados

De certo modo,podemos dizer que a bagé uma coleção de elementos que admite repetição,já conjunto não admite repetição.

Com isso,temos resultados interessantes ao se usar UNIONe UNION ALL. Como conjunto não admite repetição,o UNIONcomparará todas as tuplas e retornará apenas as únicas. Por uma questão de performance,a primeira operação a ser realizada será uma ordenação total das tuplas (tempo o(n log n)) para então eliminar as repetições (tempo o(n)). Se ele não fizesse essa ordenação antes da verificação dos únicos,teria um tempo de execução quadrático.

Normalmente se trabalha com números,strings e datas em um banco de dados,então nesse conjunto universo é possível obter uma ordenação. Pôde-se também usar uma heurística para ordenação de blobs,tratando-os como uma palavra de bytes e ordená-los lexicograficamente,mantendo portanto uma ordenação mais “natural”. Para o caso de enumerações,como elas possuem rótulos em strings,poderíamos usar esses rótulos e continuar com uma ordenação no conjunto (embora essa ordenação agora não seja mais uma ordenação natural).

Então,por questão de performance,ao requisitar um UNION,normalmente o SGBD guardará todo o resultado da consulta,executará uma única ordenação no final de tudo e então obterá o resultado de tuplas únicas. Ele não faz ordenamentos parciais do conjunto de dados pois é extremamente ruim para a performance;executar uma ordenação a cada mdados novos significa rodar o(n/m)vezes uma ordenação de o(n log n),o que pode acabar ficando pior até mesmo que uma ordenação quadrática se mfor mal escolhido.

Isso tudo implica que UNIONnão tem alta disponibilidade,pois só começará a retornar após obter todos os dados.

UNION ALL,como tem como resultado uma bag,não precisa obter previamente todo o resultado para então devolver. No momento que um resultado é obtido,ele já pode responder imediatamente a quem fez a consulta,esquecer desse valor é pegar o próximo. Isso torna sua disponibilidademuito maior. Sem falar que potencialmente,dependendo de como foi implementado o motor de SQL usado,o resultado desse operador não precisa ser armazenado em memória,podendo ser retornado imediatamente para quem o chamou utilizar o dado obtido.

Por ventura,pode-se necessitar de se trabalhar com conjuntospropriamente ditos,não com bags,mas nem por isso você precisará usar UNION. Claro,isso vai depender extremamente da semântica de cada caso,não recomendo portanto generalizar. Vou dar um exemplo em que é possível obter um conjunto a partir do uso de UNION ALL.

Com base na modelagem a seguir:

[relacionamento via multiplexação, onde uma tabela aponta hipoteticamente para 3 outras a partir de uma chave estrangeira multiplexada pelo valor de outra coluna]
[relacionamento via multiplexação,onde uma tabela aponta hipoteticamente para 3 outras a partir de uma chave estrangeira multiplexada pelo valor de outra coluna]
Eu preciso resgatar o nome e código de todos os correntistas,assim como se ele é “supervisor”,“vendedor”ou “cliente”. A chave estrangeira em “conta_corrente”é cd_usuario,que por sua vez se liga com cd_cliente,ou cd_vendedor,ou cd_supervisor,dependendo da muliplexação. No meu caso,cada correntista só pode ter no máximo uma conta corrente. A consulta ficaria assim:

SELECTcd_usuario,"cliente" AStp_correntista,nm_cliente ASnm_correntista
FROMconta_corrente cc INNERJOINcliente c ON(c.cd_cliente =cc.cd_usuario)
WHEREcc.tp_conta ='c'UNIONSELECTcd_usuario,"vendedor" AStp_correntista,nm_vendedor ASnm_correntista
FROMconta_corrente cc INNERJOINvendedor v ON(v.cd_vendedor =cc.cd_usuario)
WHEREcc.tp_conta ='v'UNIONSELECTcd_usuario,"supervisor" AStp_correntista,nm_supervisor ASnm_correntista
FROMconta_corrente cc INNERJOINsupervisor s ON(s.cd_supervisor =cc.cd_usuario)
WHEREcc.tp_conta ='s'

Pronto,a consulta retorna um conjunto como esperado. Agora,notou como não é possível que,por acaso,haja uma igualdade de tuplas entre,digamos,a primeira consulta e a segunda consulta? Isso porque todos os elementos da primeira consulta terão como segundo elemento de suas tuplas o valor “cliente”,já os da segunda consulta o valor na mesma posição seria “vendedor”. Além disso,como cd_clienteé chave primária da tabela clientee cada clientenesse modelo só está atrelado a no máximo um elemento da tabela conta_corrente,então não tem choque de tuplas dentro de cada consulta individual,portanto cada uma das 3 consultas acima resulta num conjunto.

Como já temos 3 conjuntos,e temos garantia que nenhum desses conjuntos tem elemento em comum com outro conjunto,a operação de “soma”terá o mesmo resultado final que a “soma”de bags. Portanto,em casos assim,o uso do UNION ALLgarante o resultado desejado e também garante uma melhor performance (teoricamente pelo menos).

A consulta então pode ser reescrita assim:

SELECTcd_usuario,"cliente" AStp_correntista,nm_cliente ASnm_correntista
FROMconta_corrente cc INNERJOINcliente c ON(c.cd_cliente =cc.cd_usuario)
WHEREcc.tp_conta ='c'UNIONALLSELECTcd_usuario,"vendedor" AStp_correntista,nm_vendedor ASnm_correntista
FROMconta_corrente cc INNERJOINvendedor v ON(v.cd_vendedor =cc.cd_usuario)
WHEREcc.tp_conta ='v'UNIONALLSELECTcd_usuario,"supervisor" AStp_correntista,nm_supervisor ASnm_correntista
FROMconta_corrente cc INNERJOINsupervisor s ON(s.cd_supervisor =cc.cd_usuario)
WHEREcc.tp_conta ='s'
LEIA TAMBÉM:

Complexidade de Algoritimo,o que é?

Compartilhe:

Ramos da Informática
Ramos da Informáticahttps://ramosdainformatica.com.br
Ramos da Informática é um hub de comunidade sobre linguagens de programação, banco de dados, DevOps, Internet das Coisas, tecnologia da indústria 4.0, Cyber Segurança e Startups.

RECENTES

Claude Sonnet 4.5: Mais Avançado para Programação e Automação

A Anthropic acaba de lançar o Claude Sonnet 4.5,...

AP2 do Google: Desenvolva Pagamentos para agentes de IA

O Google lançou o Agent Payments Protocol (AP2), um...

Curso gratuito de GitHub Copilot para devs e estudantes

A Microsoft abriu as inscrições para o primeiro Bootcamp...

Santander e a Alura oferecem 60.000 bolsas em carreira de tecnologia

Quer dar um salto na sua carreira? O Santander Imersão Digital está...

Google Tradutor desafia o Duolingo com novas ferramentas de aprendizagem de idiomas

O Google está lançando um novo recurso experimental com...

A peça que faltava para agentes de IA autônomos.

Este artigo foi originalmente publicado em: https://www.linkedin.com/newsletters/ezine-dev-ramos-da-inform%25C3%25A1tica-6947960536550526976/ A inteligência...
Newsletter semanal no LinkedIn
EZine Dev Ramos da Informática
Grandes dicas em JavaScript, Node, React, Next, Banco de Dados & IA.
Assinar grátis
Abre em nova aba
spot_img