SQL UNION vs UNION ALL: diferenças, exemplos e desempenho testado

  1. Início
  2. Blog
  3. Bancos de dados e SQL

Bancos de dados e SQL

SQL UNION vs UNION ALL: Diferenças, exemplos e desempenho testado

A diferença entre eles é uma palavra, mas escolher errado pode silenciosamente resultar no total errado. Veja ambos em dados reais, aprenda as regras que eles compartilham e leia o que aconteceu quando os cronometramos em um milhão de linhas.

8 min de leitura
SQL UNION vs UNION ALL: diferenças, exemplos e desempenho testado

Principais pontos

  • UNION combina resultados e remove linhas duplicadas. UNION ALL mantém todas as linhas.
  • A desduplicação de custos funciona, portanto UNION ALL geralmente é mais rápido de calcular.
  • Usar UNION antes de SUM pode remover silenciosamente valores reais e fornecer a resposta errada.
  • O padrão é UNION ALL, a menos que você queira especificamente remover duplicatas.

Ambos os operadores empilham os resultados de duas consultas um sobre o outro, então SQL UNION vs UNION ALL pode parecer uma escolha secundária. Não é. Uma palavra extra altera o resultado e o esforço do banco de dados para funcionar.

Executamos todas as consultas aqui no SQLite 3.50, e os resultados e tempos mostrados vêm dessas execuções. O comportamento básico é o SQL padrão nos principais bancos de dados. Os tempos, no entanto, serão diferentes em seu próprio banco de dados, dados e hardware, portanto, trate os nossos como uma ilustração.

A resposta curta

UNION combina dois conjuntos de resultados e retorna apenas linhas distintas. UNION ALL combina-os e retorna tudo, inclusive duplicatas. Essa é toda a diferença, e o restante deste artigo explica por que isso é importante.

UNIÃO vs UNIÃO TODOS lado a lado

Aspecto UNIÃO UNIÃO TODOS
Linhas duplicadas Removido Mantido
Trabalho extra Deve encontrar duplicatas Nenhum
Velocidade normal Mais lento Mais rápido
Linhas retornadas Igual ou menos Todos eles
Seguro antes de SUM ou COUNT? Muitas vezes não Sim
Melhor para Listas exclusivas Mesclando dados, logs, totais

Os dados de amostra

Imagine uma loja que mantém os pedidos online e presenciais em tabelas separadas. Observe que Asha tem dois pedidos online idênticos e um pedido idêntico na loja.

CREATE TABLE online_orders (customer TEXT, total INT);
CREATE TABLE store_orders (customer TEXT, total INT);

INSERT INTO online_orders VALUES ('Asha',100), ('Ben',200), ('Asha',100);
INSERT INTO store_orders VALUES ('Asha',100), ('Dev',300);

Veja a diferença

SELECT customer, total FROM online_orders
UNION
SELECT customer, total FROM store_orders;

-- Asha | 100
-- Ben  | 200
-- Dev  | 300
SELECT customer, total FROM online_orders
UNION ALL
SELECT customer, total FROM store_orders;

-- Asha | 100
-- Ben  | 200
-- Asha | 100
-- Asha | 100
-- Dev  | 300

Cinco linhas de entrada tornaram-se três com UNION e todas as cinco permaneceram com UNION ALL. Duas coisas a serem observadas:

  • UNION removeu duplicatas de todo o resultado, incluindo aquelas da primeira tabela. Não se trata apenas de comparar tabelas.
  • Uma linha conta como duplicada somente quando todas as colunas selecionadas correspondem.

Quando você realmente deseja uma lista distinta, UNION está exatamente certo. Isso dá a cada cliente que comprou por meio de qualquer canal:

SELECT customer FROM online_orders
UNION
SELECT customer FROM store_orders;

-- Asha
-- Ben
-- Dev

O bug do total errado

Esta é a razão pela qual a escolha realmente importa. Suponha que você queira a receita total. Os pedidos acima somam 800. Veja o que cada operadora dá:

SELECT SUM(total) FROM (
  SELECT total FROM online_orders
  UNION
  SELECT total FROM store_orders
);
-- 600

SELECT SUM(total) FROM (
  SELECT total FROM online_orders
  UNION ALL
  SELECT total FROM store_orders
);
-- 800

A versão UNION está errada em 200. Como selecionamos apenas a coluna total, três pedidos separados de 100 rúpias pareciam duplicados e se uniram em um. Não há mensagem de erro e 600 parece um número perfeitamente verossímil. Esse tipo de bug silencioso pode permanecer em um relatório financeiro por meses.

Dica: Duas linhas de aparência idêntica podem ser dois eventos genuínos. Antes de usar UNION, pergunte se linhas idênticas significam o mesmo fato registrado duas vezes ou dois fatos diferentes. Para vendas, pagamentos e lançamentos de log, geralmente é o segundo.

Regras que ambos devem seguir

Ambas as operadoras têm os mesmos requisitos:

  1. Cada SELECT deve retornar o mesmo número de colunas.
  2. As colunas são correspondidas por posição, e não por nome, portanto, mantenha-as na mesma ordem.
  3. Os tipos de dados em cada posição devem ser compatíveis.
  4. Os nomes das colunas de resultados vêm do primeiro SELECT.
  5. ORDER BY vai bem no final e se aplica a todo o resultado.

Quebrar a primeira regra gera um erro. Aqui está a mensagem do SQLite:

SELECT customer, total FROM online_orders
UNION
SELECT customer FROM store_orders;

-- SELECTs to the left and right of UNION do not have
-- the same number of result columns

A segunda regra é mais perigosa porque pode falhar sem cometer erros. Se você trocar duas colunas do mesmo tipo, como first_name e last_name, a consulta será executada e os dados sairão errados. SQLite também é relaxado em relação aos tipos, enquanto bancos de dados como PostgreSQL são mais rígidos e podem exigir uma especificação explícita CAST.

Rotule a fonte

Um truque muito prático é adicionar uma coluna constante mostrando de onde veio cada linha. Como o rótulo é diferente, as linhas de tabelas diferentes não podem mais ser tratadas como duplicatas umas das outras.

SELECT customer, total, 'online' AS channel FROM online_orders
UNION ALL
SELECT customer, total, 'store' FROM store_orders
ORDER BY customer, channel;

-- Asha | 100 | online
-- Asha | 100 | online
-- Asha | 100 | store
-- Ben  | 200 | online
-- Dev  | 300 | store

Depois que seus dados tiverem um rótulo, você poderá agrupá-los para gerar relatórios de vendas por canal, usando GROUP BY. Se você precisar combinar várias etapas, envolva a união em um CTE para mantê-la legível.

Desempenho: o que aconteceu em nosso teste

Para remover duplicatas, o banco de dados precisa comparar as linhas, normalmente classificando-as ou fazendo hash. UNION ALL pode pular esta etapa. Criamos duas tabelas com 500.000 linhas cada, contendo números aleatórios de 0 a 50.000, portanto havia muitas duplicatas. Executamos cada consulta várias vezes e mantivemos o melhor tempo.

Primeiro, contamos os resultados, para que o tempo gasto no envio de linhas de volta ao nosso programa não afetasse a comparação:

Consulta, envolvida em COUNT(*) Linhas Melhor horário
UNIÃO 50,001 261ms
UNIÃO TODOS 1,000,000 Menos de 1 ms

A enorme lacuna ocorre em parte porque o SQLite pode calcular essa contagem sem ler todas as linhas, portanto, não leia isso como “milhares de vezes mais rápido”. Porém, isso mostra a ideia central: UNION teve que fazer um trabalho real e UNION ALL não o fez.

Em seguida, buscamos todas as linhas no Python e o resultado mudou:

Consulta, buscando todas as linhas Linhas retornadas Melhor horário
UNIÃO 50,001 277ms
UNIÃO TODOS 1,000,000 392ms

Aqui, UNION ALL demorou mais porque entregou vinte vezes mais linhas. A desduplicação não foi o que o atrasou. Lidar com um milhão de linhas foi. Portanto, a regra honesta é que UNION ALL é mais barato para o banco de dados calcular, mas o tamanho do resultado também é importante. Muitos gráficos online reduzem isso para “UNION ALL é sempre mais rápido”, e nosso teste mostra por que não é tão simples.

Também não escolha apenas com base na velocidade. Escolha primeiro o operador que dá a resposta correta e depois ajuste. Se uma consulta for lenta, leia nosso guia sobre otimização de consultas SQL.

Quando usar cada

Use UNION ALL quando:

  • Você está mesclando dados de tabelas semelhantes, como partições mensais.
  • Você calculará totais ou contagens posteriormente.
  • Você sabe que as entradas não podem se sobrepor.
  • As duplicatas são significativas, como em logs ou registros de auditoria.

Use UNION quando:

  • Você precisa de uma lista exclusiva, como todos os endereços de e-mail em dois sistemas.
  • Fontes sobrepostas contêm o mesmo fato mais de uma vez.

Trate UNION ALL como padrão e use UNION deliberadamente. Adicionar uma cláusula WHERE a cada ramificação, para filtrar antecipadamente, ajuda ambos.

INTERSETAR e EXCETAR

Dois operadores de conjuntos relacionados respondem a perguntas diferentes. Ambos seguem as mesmas regras de coluna:

SELECT customer FROM online_orders
INTERSECT
SELECT customer FROM store_orders;
-- Asha  (bought in both channels)

SELECT customer FROM online_orders
EXCEPT
SELECT customer FROM store_orders;
-- Ben   (online only)

A Oracle tradicionalmente usa MINUS em vez de EXCEPT, e o suporte para esses operadores varia um pouco de acordo com o banco de dados e a versão.

UNIÃO vs JUNTE-SE

Muitas vezes são confundidos, mas combinam dados em direções diferentes:

Operação Direção Resultado
UNIÃO Verticais Adiciona mais linhas
PARTICIPE Horizontais Adiciona mais colunas

Erros comuns

  • Usar UNION por hábito. Isso pode custar velocidade ou remover linhas válidas.
  • Selecionar poucas colunas. Deixar um ID de fora faz com que linhas distintas pareçam idênticas.
  • Ordem das colunas incompatível. Os valores podem chegar à coluna errada sem nenhum erro.
  • Adicionando ORDER BY a cada ramificação. Classifique uma vez, no final.
  • Usando UNION para corrigir uma junção incorreta. Se aparecerem duplicatas devido a uma junção, corrija a junção.
  • Assumindo a ordem dos resultados. Sem ORDER BY, a ordem das linhas não é garantida para nenhum dos operadores.

Considerações finais

Faça uma pergunta de cada vez: linhas idênticas são o mesmo fato ou fatos separados? Se eles estiverem separados ou se a sobreposição for impossível, use UNION ALL. Se você precisar de uma lista exclusiva, use UNION. Para verificar seus próprios relatórios, pesquise UNION em seu código perto de SUM ou COUNT e confirme se esses totais realmente estão corretos.

Perguntas frequentes

Qual é a diferença entre UNION e UNION ALL?

UNION combina dois conjuntos de resultados e remove linhas duplicadas. UNION ALL combina-os e mantém todas as linhas, incluindo duplicatas.

Qual é mais rápido, UNION ou UNION ALL?

UNION ALL geralmente é mais barato de calcular, porque não verifica duplicatas. Retornar um resultado muito maior ainda pode demorar mais, como mostrou nosso teste.

UNION remove duplicatas em uma tabela?

Sim. Ele remove duplicatas em todo o resultado combinado, incluindo linhas idênticas provenientes da mesma tabela.

Os nomes das colunas precisam corresponder em um UNION?

Não. As colunas são correspondidas por posição e o resultado usa nomes do primeiro SELECT. A contagem de colunas deve corresponder e os tipos devem ser compatíveis.

Posso usar ORDER BY com UNION?

Sim, mas coloque um ORDER BY no final da instrução. Ele classifica todo o resultado combinado em vez de uma única ramificação.

Continue aprendendo

Trabalhe com Stack Quora

Precisa de ajuda com testes, WordPress ou SEO?

Ajudamos as equipes a fornecer software melhor e a expandir seus sites. Conte-nos no que você está trabalhando e sugeriremos um próximo passo claro.

Continue lendo

Mais guias sobre testes, IA e desenvolvimento moderno

Gostou deste artigo? Escolha um tópico e vá direto para nossos tutoriais mais recentes.

Inteligência artificial

Explicação das alucinações de IA: por que os modelos de linguagem inventam as coisas e como reduzi-las

Explicação das alucinações de IA: o que são, por que os modelos de linguagem as produzem, tipos comuns, como reduzi-las com aterramento e instruções…

Leia o artigo →
DevOps

Variáveis de ambiente explicadas: arquivos .env, segredos e configuração bem feitos

Variáveis de ambiente explicadas com exemplos de Python que executamos: leitura e configuração, por que cada valor é uma string, arquivos .env, hera…

Leia o artigo →
Desenvolvimento de software

Explicação da limitação de taxa de API: algoritmos, cabeçalhos e tratamento de erros 429

Limitação de taxa de API explicada com uma simulação que executamos: token bucket, janela fixa, janela deslizante, 429 respostas, cabeçalhos de limi…

Leia o artigo →
Automação de testes

Zombando em Python: unittest.mock, patch e os erros que fazem os testes mentirem

Zombaria em Python com unittest.mock, testado: Mock e return_value, side_effect, patch onde um nome é usado, especificação e autospec, zombaria de d…

Leia o artigo →
Teste de software

Cobertura de código explicada: cobertura de linha versus filial e o que 100% realmente significa

Cobertura de código explicada com uma execução cobertura.py real: cobertura de linha, ramal e condição, leitura de um relatório, por que 100% de cob…

Leia o artigo →
Bancos de dados e SQL

DELETE vs TRUNCATE vs DROP em SQL: diferenças, reversão e quando usar cada um

DELETE vs TRUNCATE vs DROP explicado com SQL testado: o que cada um remove, rollback, aciona, redefinição de identidade, velocidade e como PostgreSQ…

Leia o artigo →
Bancos de dados e SQL

Exibições SQL explicadas: crie, use e evite as armadilhas, com exemplos

Visualizações SQL explicadas com consultas que executamos: criação de uma visualização, resultados ao vivo, ocultação de colunas, desempenho, visual…

Leia o artigo →
Desenvolvimento de software

Interface TypeScript vs tipo: diferenças reais, testadas com o compilador

Interface TypeScript versus tipo, verificada com o compilador real: o que ambos podem fazer, o que apenas um pode fazer, mesclagem de declarações, e…

Leia o artigo →
Desenvolvimento de software

Python *args e **kwargs explicados: funções flexíveis com exemplos claros

Python *args e **kwargs explicados com o código que executamos: empacotamento e descompactação, ordem dos parâmetros, argumentos somente de palavras…

Leia o artigo →
Desenvolvimento de software

Funções Python Lambda: sintaxe, usos reais e quando não usá-los

Funções lambda do Python explicadas com o código que executamos: sintaxe, classificação com chave, mapa e filtro, fechamentos, armadilha de ligação …

Leia o artigo →
Inteligência artificial

O que são agentes de IA? Como eles funcionam, com um loop de agente simples que você pode executar

O que são agentes de IA? Um guia simples para o loop do agente, ferramentas, memória e proteções, com um pequeno loop Python que executamos, riscos …

Leia o artigo →
DevOps

Monitoramento versus observabilidade: a verdadeira diferença, com logs, métricas e rastreamentos

Explicação do monitoramento versus observabilidade: falhas conhecidas e desconhecidas, logs, métricas e rastreamentos, um passo a passo do incidente…

Leia o artigo →
DevOps

Docker Volumes vs Bind Mounts: persista os dados do contêiner da maneira certa

Volumes Docker versus montagens de ligação explicadas: por que os dados do contêiner desaparecem, volumes nomeados, montagens de ligação, tmpfs, exe…

Leia o artigo →
Automação de testes

TDD vs BDD: principais diferenças, um recurso criado de ambas as maneiras e quando usar cada um

TDD vs BDD explicado com um recurso de desconto construído em ambos os sentidos: refatoração vermelho-verde com o código que executamos, cenários da…

Leia o artigo →
Teste de software

Teste de aceitação do usuário (UAT): processo, lista de verificação e exemplos reais

Explicação do teste de aceitação do usuário: quem o executa, como ele difere do controle de qualidade, um processo de sete etapas, um modelo de caso…

Leia o artigo →
Bancos de dados e SQL

Valores SQL NULL explicados: IS NULL, COALESCE, NULLIF e as armadilhas a serem evitadas

Valores SQL NULL explicados com consultas que executamos: lógica de três valores, IS NULL, COALESCE, NULLIF, como agregações, junções e classificaçã…

Leia o artigo →
Bancos de dados e SQL

Instrução SQL CASE WHEN: sintaxe, exemplos reais e erros comuns

SQL CASE WHEN explicado com consultas que executamos: formulários simples e pesquisados, ordem de condição, pivôs com SUM, truques COUNT, classifica…

Leia o artigo →
Desenvolvimento de software

O que é JWT? JSON Web Tokens explicados com um exemplo prático

O que é JWT? JSON Web Tokens explicados: as três partes, um token construído e adulterado no código que executamos, JWT vs sessões, armazenamento, t…

Leia o artigo →
Desenvolvimento de software

Loop de eventos JavaScript explicado: pilha de chamadas, microtarefas e temporizadores com exemplos

O loop de eventos JavaScript explicado com o código que executamos: pilha de chamadas, filas de tarefas e microtarefas, por que setTimeout 0 não é i…

Leia o artigo →
Desenvolvimento de software

Geradores Python e rendimento explicado: economize memória com exemplos reais

Geradores Python e rendimento explicados com o código que executamos: como eles pausam e reiniciam, medem economia de memória, pipelines, sequências…

Leia o artigo →
Inteligência artificial

O que são incorporações? Similaridade de vetores e cossenos explicada de forma simples

O que são incorporações? Um guia em linguagem simples para vetores, similaridade de cossenos e pesquisa semântica, com um pequeno exemplo que execut…

Leia o artigo →
DevOps

Implantação azul-verde vs canário: diferenças, compensações e como escolher

Explicação da implantação azul-verde versus canário: como cada um funciona, custo, risco e reversão, agrupamento estável de usuários que testamos, m…

Leia o artigo →
Automação de testes

Testes instáveis: o que os causa e como corrigi-los para sempre

Testes instáveis explicados com demonstrações que executamos: as principais causas, como confirmar e diagnosticar uma, soluções adequadas para tempo…

Leia o artigo →
Teste de software

Teste de carga versus teste de estresse: diferenças, métricas e exemplos k6

Teste de carga versus teste de estresse explicado: o que cada um prova, testes de pico e absorção, as métricas que importam, por que as médias engan…

Leia o artigo →
Teste de software

Caso de teste versus cenário de teste: principais diferenças, exemplos e quando usar cada um

Caso de teste vs cenário de teste explicado: definições claras, uma tabela lado a lado, um recurso de redefinição de senha retirado de cenários para…

Leia o artigo →
Bancos de dados e SQL

Otimização de consultas SQL: leia planos de execução e corrija consultas lentas, com intervalos

Otimização de consulta SQL testada em um milhão de linhas: leia planos de execução, adicione os índices corretos, corrija filtros não sargáveis, use…

Leia o artigo →
Bancos de dados e SQL

SQL UNION vs UNION ALL: diferenças, exemplos e desempenho testado

SQL UNION vs UNION ALL explicado com consultas que executamos: duplicatas, as regras que ambos seguem, um bug de dados real, desempenho medido, INTE…

Leia o artigo →
Desenvolvimento de software

Tutorial da API JavaScript Fetch: GET, POST, tratamento de erros e tempos limite

Um tutorial da API JavaScript Fetch testado em um servidor local: GET e POST, por que 404 não lança, um auxiliar reutilizável, strings de consulta, …

Leia o artigo →
Desenvolvimento de software

Manipulação de arquivos Python: leitura, gravação, CSV, JSON e pathlib com exemplos

Manipulação de arquivos Python explicada com código que executamos: modos abertos, com, leitura de arquivos grandes, CSV, JSON, pathlib, arquivos bi…

Leia o artigo →
Desenvolvimento de software

Git merge vs rebase: diferenças, exemplos e quando usar cada um

Git merge vs rebase explicado com saída real do log, uma tabela comparativa, a regra de ouro do rebase e um fluxo de trabalho seguro para equipes.

Leia o artigo →
Desenvolvimento de software

List comprehension em Python: sintaxe, exemplos e quando evitar

List comprehension em Python explicada: sintaxe, filtros, if-else, laços aninhados, tempos medidos e quando um laço for comum é a melhor escolha.

Leia o artigo →
Bancos de dados e SQL

SQL JOIN explicado com exemplos (Inner, Left, Right, Full)

Entenda os joins SQL passo a passo com tabelas e consultas de exemplo: INNER, LEFT, RIGHT, FULL, CROSS e SELF, além de erros comuns e dicas de desem…

Leia o artigo →