SQL UNION

A Ana quer saber em quais cidades a Loja Aurora tem alguém: um cliente ou um fornecedor. Os clientes estão numa tabela, os fornecedores em outra. Ela poderia rodar duas consultas e juntar as listas à mão, riscando as cidades repetidas. O UNION (em inglês, "união") faz isso por ela: empilha o resultado de duas consultas numa lista só e tira as linhas repetidas.

Você vai aprender
  • O que o UNION faz e como ele é diferente de um JOIN.
  • As regras: o mesmo número de colunas, na mesma ordem, e os nomes vindos do primeiro SELECT.
  • Por que o UNION tira as repetições, até as de dentro de uma mesma consulta.
  • Onde vai o ORDER BY (só no fim) e o LIMIT.
  • Como marcar de onde veio cada linha com uma coluna de "origem".
  • Quando um OR resolve e quando só o UNION resolve.
  • Os erros reais do SQLite: colunas a mais, ORDER BY no meio, parênteses.

Todos os exemplos rodam de verdade no seu navegador, no banco da Loja Aurora (veja O Banco da Loja Aurora).


A ideia: duas listas de convidados

A Ana e o irmão vão dar uma festa e cada um fez a sua lista de convidados. Para mandar os convites, ela põe uma folha embaixo da outra e passa a limpo, escrevendo cada nome uma vez só: quem estava nas duas listas não ganha dois convites. Isso é o UNION.

Repare na diferença para o JOIN, que você viu nas aulas anteriores:

JOINUNION
O que juntaTabelas, lado a ladoResultados de consultas, um embaixo do outro
O resultado ganhaMais colunasMais linhas
Precisa deUma regra de ligação (ON)O mesmo número de colunas nas duas consultas
Na festaPôr ao lado de cada convidado o telefone deleJuntar as duas listas de convidados numa só

1. As duas listas

Primeiro, cada lista sozinha. As cidades dos clientes, sem repetir (aula SELECT DISTINCT):

SELECT DISTINCT cidade FROM clientes;

E as cidades dos fornecedores:

SELECT cidade FROM fornecedores;

São 8 cidades de clientes e 6 linhas de fornecedores, com Teresina duas vezes (a loja tem dois fornecedores lá). Algumas cidades estão nas duas listas: Teresina, Fortaleza e São Paulo.


2. O primeiro UNION

Agora as duas listas numa só:

SELECT cidade FROM clientes
UNION
SELECT cidade FROM fornecedores;
SELECT cidade FROM clientes
A primeira consulta: uma consulta completa, que funcionaria sozinha.
UNION
"Junte com o resultado da próxima consulta e tire as linhas repetidas." Ele fica entre as duas consultas, sem ponto e vírgula antes: é tudo um comando só.
SELECT cidade FROM fornecedores
A segunda consulta, também completa. O ; vem só no fim de tudo.

O resultado tem 10 cidades. Faça a conta: 8 de clientes + 6 de fornecedores = 14 linhas, menos as repetidas. Teresina, Fortaleza e São Paulo, que estavam nas duas listas, aparecem uma vez só, e o Teresina repetido dos fornecedores também sumiu. As duas cidades novas vêm dos fornecedores estrangeiros: Porto e Buenos Aires.

A ordem do resultado

Aqui as cidades saíram em ordem alfabética, mas isso foi efeito do jeito como o SQLite tirou as repetições, e não uma promessa. Sem ORDER BY, nenhum banco garante a ordem. Quer em ordem? Peça (seção 4).


3. As regras das colunas

O UNION empilha linhas, então as linhas das duas consultas precisam "encaixar" uma embaixo da outra:

  1. O mesmo número de colunas. Se a primeira consulta tem 2 colunas, a segunda também tem de ter 2. Senão o SQLite recusa (veja Quando dá errado).
  2. Na mesma ordem. A 1ª coluna de uma vai embaixo da 1ª coluna da outra, a 2ª embaixo da 2ª. O banco não olha os nomes, só a posição.
  3. Os nomes vêm da primeira consulta. O cabeçalho do resultado é o da primeira consulta; os nomes (e os AS) das outras são ignorados.

Um exemplo com duas colunas. A Ana quer a lista de contatos de Teresina: clientes e fornecedores. Para saber quem é quem, ela cria uma coluna com um texto fixo:

SELECT nome, 'cliente' AS tipo
FROM clientes
WHERE cidade = 'Teresina'
UNION
SELECT nome, 'fornecedor'
FROM fornecedores
WHERE cidade = 'Teresina'
ORDER BY nome;
'cliente' AS tipo
Um texto fixo, que se repete em toda linha dessa consulta. Ele vira a 2ª coluna, com o nome tipo.
'fornecedor'
A 2ª coluna da segunda consulta. Não precisa de AS: o nome tipo já veio da primeira.
WHERE … em cada parte
Cada consulta tem o seu próprio WHERE. O primeiro filtra os clientes; o segundo, os fornecedores.
ORDER BY nome
Ordena a lista inteira, já unida. Ele vem uma vez só, no fim.

São 10 clientes de Teresina e 2 fornecedores, 12 contatos misturados em ordem alfabética. Essa coluna de "origem" com texto fixo é um truque muito usado com UNION, porque sem ela não dá para saber de qual tabela veio cada linha.


4. ORDER BY e LIMIT: só no fim

O ORDER BY e o LIMIT valem para o resultado já unido, por isso só podem aparecer uma vez, depois da última consulta. Você pode ordenar pelo nome da coluna (o nome da primeira consulta) ou pelo número da posição:

SELECT nome FROM funcionarios
UNION
SELECT nome FROM fornecedores
ORDER BY 1
LIMIT 3;

ORDER BY 1 quer dizer "pela 1ª coluna". O LIMIT 3 (aula LIMIT e OFFSET) pegou as 3 primeiras da lista toda, e não 3 de cada tabela: funcionários e fornecedores estão misturados.

Missão: a Ana quer uma lista só com os nomes de todos os funcionários e de todos os fornecedores, em ordem alfabética. Hoje a consulta só tem os funcionários. Acrescente os fornecedores com UNION e mantenha a ordem alfabética da lista inteira.

SELECT nome FROM funcionarios
ORDER BY nome;
SELECT nome FROM funcionarios
UNION
SELECT nome FROM fornecedores
ORDER BY nome;

5. O UNION tira toda repetição

O UNION não tira só o que se repete entre as consultas. Ele tira qualquer linha igual a outra no resultado final, mesmo que as duas tenham vindo da mesma consulta. Veja o caso extremo, a mesma tabela duas vezes:

SELECT cidade FROM clientes
UNION
SELECT cidade FROM clientes;

Saíram as 8 cidades, sem repetição, igual ao SELECT DISTINCT cidade FROM clientes da seção 1. Os 30 clientes, duas vezes, viraram 8 linhas.

"Linha repetida" quer dizer todas as colunas iguais. Na lista de contatos de Teresina, se existisse um fornecedor chamado "Tiago Fontes", ele não seria repetição do cliente Tiago Fontes, porque a coluna tipo é diferente (fornecedor × cliente).

Às vezes você quer as repetições: para contar, por exemplo. Para isso existe o UNION ALL, que empilha tudo sem tirar nada. Ele tem aula própria, a próxima: UNION ALL.


6. Três consultas ou mais

Dá para encadear quantos UNION você quiser. Aqui, uma lista com três origens diferentes: os clientes de Recife, os fornecedores estrangeiros e a funcionária que não tem chefe (a gerente):

SELECT nome, 'cliente' AS origem
FROM clientes WHERE cidade = 'Recife'
UNION
SELECT nome, 'fornecedor'
FROM fornecedores WHERE pais <> 'Brasil'
UNION
SELECT nome, 'funcionária'
FROM funcionarios WHERE chefe_id IS NULL
ORDER BY origem, nome;

Três tabelas diferentes, uma lista só, ordenada primeiro pela origem e depois pelo nome. As três consultas têm 2 colunas cada uma, e o ORDER BY continua uma vez só, no fim.


7. UNION × OR

Quando as duas listas vêm da mesma tabela, um OR (aula OR) costuma dar o mesmo resultado. Os clientes de Pernambuco ou VIP, dos dois jeitos:

SELECT nome FROM clientes WHERE estado = 'PE'
UNION
SELECT nome FROM clientes WHERE vip = 1;
SELECT nome FROM clientes
WHERE estado = 'PE' OR vip = 1;

Os mesmos 7 clientes, em ordem diferente. Com uma tabela só, o OR é mais simples e o banco lê a tabela uma vez. Mas o OR não sabe juntar duas tabelas diferentes numa lista; aí só o UNION resolve.

Você quer…Use
Linhas da mesma tabela que atendem a uma condição ou a outraWHERE … OR … (ou IN)
Uma lista só com linhas de tabelas diferentes, sem repetiçãoUNION
A mesma coisa, mas mantendo as repetições (para contar, somar)UNION ALL
Colunas de outra tabela ao lado de cada linhaJOIN, não UNION
Os parentes do UNION: INTERSECT e EXCEPT

O SQL tem mais dois operadores que juntam consultas do mesmo jeito. INTERSECT ("interseção") mostra só o que está nas duas listas; EXCEPT ("exceto") mostra o que está na primeira e não está na segunda. As mesmas regras de colunas valem para eles.

SELECT cidade FROM clientes
INTERSECT
SELECT cidade FROM fornecedores;

Teresina, Fortaleza e São Paulo: as cidades que têm cliente e fornecedor. E as cidades que só têm fornecedor:

SELECT cidade FROM fornecedores
EXCEPT
SELECT cidade FROM clientes;

Quando dá errado

Número de colunas diferente

A primeira consulta tem 2 colunas e a segunda, 1:

SELECT nome, cidade FROM clientes
UNION
SELECT nome FROM fornecedores;

A mensagem: SELECTs to the left and right of UNION do not have the same number of result columns, "os SELECTs à esquerda e à direita do UNION não têm o mesmo número de colunas no resultado". É o erro mais comum com UNION. No terminal do sqlite3, a mesma mensagem vem com um prefixo:

$ sqlite3 loja.db
SQLite version 3.50.4 2025-07-30 19:33:53
Enter ".help" for usage hints.
sqlite> SELECT nome, cidade FROM clientes UNION SELECT nome FROM fornecedores;
Parse error: SELECTs to the left and right of UNION do not have the same number of result columns

Como consertar: conte as colunas de cada consulta e deixe iguais: acrescente a coluna que falta (SELECT nome, cidade FROM fornecedores) ou tire a que sobra.

ORDER BY no meio
SELECT nome FROM clientes
ORDER BY nome
UNION
SELECT nome FROM fornecedores;

A mensagem: ORDER BY clause should come after UNION not before, "a cláusula ORDER BY deve vir depois do UNION, não antes". O SQLite até explica o que fazer.

Como consertar: mova o ORDER BY para depois da última consulta. Ele vai ordenar a lista inteira, que é quase sempre o que você queria.

Ordenar por uma coluna que não está no resultado
SELECT cidade FROM clientes
UNION
SELECT cidade FROM fornecedores
ORDER BY nome;

A mensagem: 1st ORDER BY term does not match any column in the result set, "o 1º termo do ORDER BY não corresponde a nenhuma coluna do resultado". Numa consulta simples, você pode ordenar por uma coluna que não mostra; com UNION, não: o ORDER BY só enxerga as colunas do resultado unido.

Como consertar: ordene por uma coluna que está no SELECT (ORDER BY cidade) ou pela posição (ORDER BY 1).

Parênteses em volta de cada consulta
(SELECT nome FROM funcionarios)
UNION
(SELECT nome FROM fornecedores);

A mensagem: near "(": syntax error, "erro de sintaxe perto de (". Em outros bancos essa escrita é aceita (veja a nota abaixo), por isso ela aparece em muito tutorial; o SQLite não aceita.

Como consertar: tire os parênteses. Se você queria um ORDER BY ou LIMIT só numa das partes, ponha essa parte como subconsulta no FROM:

SELECT nome FROM (SELECT nome FROM funcionarios ORDER BY salario DESC LIMIT 2)
UNION
SELECT nome FROM fornecedores WHERE pais <> 'Brasil';

Os 2 funcionários de maior salário (Marta e Luana) e os 2 fornecedores estrangeiros. Subconsultas têm aula própria: Subconsultas.

Colunas na ordem trocada: sem erro, mas errado
SELECT nome, cidade FROM clientes WHERE cidade = 'Recife'
UNION
SELECT cidade, nome FROM fornecedores WHERE pais <> 'Brasil';

O que acontece: nenhum erro, mas "Buenos Aires" e "Porto" foram parar na coluna nome, e os nomes dos fornecedores na coluna cidade. O UNION encaixa por posição, não por nome. E o SQLite não confere se o tipo combina: ele aceita até empilhar um número embaixo de um texto.

Como consertar: escreva as colunas na mesma ordem em todas as consultas: SELECT nome, cidade FROM fornecedores.

Nos outros bancos

No MySQL, no PostgreSQL e no SQL Server o UNION funciona do mesmo jeito: mesmo número de colunas, repetições removidas, nomes vindos da primeira consulta e ORDER BY no fim. Duas diferenças:

  • Tipos. O PostgreSQL e o SQL Server exigem que as colunas de mesma posição tenham tipos compatíveis; o SQLite não confere.
  • Parênteses. O MySQL e o PostgreSQL aceitam cada consulta entre parênteses, e é assim que eles põem um ORDER BY ou LIMIT numa parte só. Este trecho é ilustrativo (não roda no SQLite):
(SELECT nome FROM funcionarios ORDER BY salario DESC LIMIT 2)
UNION
(SELECT nome FROM fornecedores WHERE pais <> 'Brasil');

Referência rápida

EscritaO que faz
SELECT … UNION SELECT …Empilha os dois resultados e tira as linhas repetidas
SELECT … UNION SELECT … UNION SELECT …Três ou mais consultas numa lista só
'cliente' AS origemColuna de texto fixo para saber de onde veio cada linha
… ORDER BY nome / ORDER BY 1Ordena a lista inteira; só no fim, uma vez
… LIMIT 3Limita a lista inteira; só no fim
UNION ALLEmpilha sem tirar repetições (próxima aula)
INTERSECT / EXCEPTO que está nas duas listas / o que está só na primeira
Mensagem do SQLiteQuer dizer
SELECTs to the left and right of UNION do not have the same number of result columnsAs consultas têm números de colunas diferentes
ORDER BY clause should come after UNION not beforeO ORDER BY está no meio; mova para o fim
1st ORDER BY term does not match any column in the result setO ORDER BY usa uma coluna que não está no resultado
near "(": syntax errorParênteses em volta das consultas: o SQLite não aceita

Exercícios

1. A palavra que junta

Complete para empilhar os nomes dos clientes e dos fornecedores, sem repetição:

SELECT nome FROM clientes SELECT nome FROM fornecedores;

2. Contando colunas

A primeira consulta é SELECT nome, cidade, estado FROM clientes. Quantas colunas a segunda consulta do UNION precisa ter?

colunas

3. Onde vai o ORDER BY num UNION?

4. Os clientes estão em 8 cidades e os fornecedores em 5 cidades diferentes; 3 cidades aparecem nas duas listas. Quantas linhas saem do SELECT cidade FROM clientes UNION SELECT cidade FROM fornecedores?

5. De onde vêm os nomes das colunas do resultado de um UNION?

6. A Ana quer, numa lista só, os clientes VIP e os funcionários. O que ela deve usar?

Missão final: os contatos de Fortaleza

Missão: a Ana vai visitar Fortaleza e quer a lista de todos os contatos de lá: os clientes e os fornecedores, com a coluna origem dizendo quem é quem, tudo em ordem alfabética de nome. A consulta abaixo só traz os clientes. Complete-a.

SELECT nome, 'cliente' AS origem
FROM clientes
WHERE cidade = 'Fortaleza'
ORDER BY nome;
SELECT nome, 'cliente' AS origem
FROM clientes
WHERE cidade = 'Fortaleza'
UNION
SELECT nome, 'fornecedor'
FROM fornecedores
WHERE cidade = 'Fortaleza'
ORDER BY nome;

Resumo

  • UNION empilha o resultado de duas ou mais consultas numa lista só e tira as linhas repetidas (todas as colunas iguais), até as de dentro de uma mesma consulta.
  • JOIN acrescenta colunas; UNION acrescenta linhas.
  • Todas as consultas precisam do mesmo número de colunas, na mesma ordem. O encaixe é pela posição; os nomes vêm da primeira consulta.
  • ORDER BY e LIMIT vêm uma vez só, no fim, e valem para a lista inteira.
  • Uma coluna de texto fixo ('cliente' AS origem) mostra de onde veio cada linha.
  • Na mesma tabela, um OR costuma bastar; para juntar tabelas diferentes, use UNION. Para manter as repetições, UNION ALL.