Buscar
  • Ignez Mello

UNION, UNION ALL, INTERSECT e EXCEPT

Atualizado: 31 de Jul de 2019


Neste documento vamos detalhar quatro operadores muito úteis quando executamos vários SELECT com o mesmo conjunto de colunas, mas que precisam retornar registros dentro de determinadas condições.

UNION e UNION ALL

Combina o resultado de duas ou mais queries em um único resultado. As queries devem ter a mesma quantidade de colunas e na mesma ordem no SELECT, e o datatype das colunas devem ser compatíveis.

Mas qual a diferença entre UNION e UNION ALL?

  • O operador UNION elimina as linhas duplicadas. O SQL Server executa cada um dos SELECTs da query, reúne todos os resultados e então executa um SELECT DISTINCT, mesmo que não haja registros duplicados.

  • O operador UNION ALL mantém as linhas duplicadas. Ou seja, o SQL Server executa cada um dos SELECTs da query, reúne todos os resultados e então os exibe.

Vamos analisar este script:



Criamos duas tabelas temporárias: #TabA e #TabB, cada uma com 6 registros. Observe que os números 5 e 6 se repetem nas duas tabelas.

Na segunda janela, executamos um SELECT com UNION entre as tabelas, e o resultado retorna 10 linhas, pois o UNION eliminou os registros 5 e 6 duplicados.

Já na terceira janela, executamos um SELECT com UNION ALL entre as tabelas, e o resultado retorna 12 linhas, e os registros 5 e 6 aparecem duplicados.

Ainda analisando o resultado das janelas 2 e 3, o nome da coluna no resultado é Col_A. O SQL Server sempre utiliza o nome das colunas da primeira query para exibir o resultado. O nome das colunas na tabela não influencia o SELECT / UNION, desde que a quantidade de colunas em cada query e o datatype de cada coluna seja compatível, como mencionado acima.

Quando utilizamos UNION e UNION ALL, é interessante lembrar alguns pontos importantes:

  • Utilize UNION apenas quando o resultado da query não puder ter duplicidades. Se você tem certeza que não importa se o resultado trouxer linhas repetidas, sempre utilize UNION ALL. A vantagem é que UNION ALL não executa SELECT DISTINCT, ou seja, ele utiliza menos recursos do SQL Server, tornando a query mais rápida.

  • Utilizar UNION com SELECT DISTINCT é desnecessário, já que o resultado final será o mesmo, pois SELECT DISTINCT está implícito em UNION.

  • Colunas com datatype GEOGRAPH não podem ser utilizadas com UNION, mas podem ser utilizadas com UNION ALL.

  • Uma query com uma ou mais cláusulas OR no WHERE pode ser reescrita utilizando UNION ALL.

Vamos focar neste último tópico. Vejam esta query:


A consulta acima possui três colunas diferentes na cláusula WHERE. A não ser que a tabela PERSON.[Address] possua um índice cuja chave tenha essas três colunas, o SQL Server fará um Table Scan em toda a tabela.

Podemos reescrever esta query, utilizando UNION:


As duas consultas exibirão o mesmo resultado. Porém, se uma das colunas tiver um índice, mas as outras duas não, a primeira query fará o Table Scan. Na segunda query, o índice será utilizado em parte da query, melhorando a performance em geral.


INTERSECT

O operador INTERSECT executa todas as queries associadas a ele, e retorna apenas as linhas com registros iguais em todas as consultas. Vamos analisar este script e seu resultado:



Agora, vamos aplicar INTERSECT:



Analisando o conteúdo das duas tabelas, apenas o registro com o número 5 e a letra A aparecem nas duas tabelas. Como utilizamos * no SELECT, o SQL Server considerou todas as colunas para encontrar os registros que são iguais nas duas tabelas.

Mas, e se eu especificar qual coluna deve ser analisada?



Desta vez, apenas o conteúdo da coluna Numero foi analisado, e por isso duas linhas foram retornadas.

EXCEPT

O operador EXCEPT retorna todas as linhas do primeiro SELECT, exceto as linhas que aparecem nos demais SELECTs da query. Vamos utilizar o script anterior para analisar o resultado de EXCEPT, acrescentando mais uma tabela:


Primeiro, vamos executar o SELECT de todas as colunas, para visualizar o conteúdo das tabelas:


Agora, vamos aplicar EXCEPT para as tabelas #TabA e #TabB:



O que aconteceu? A query retornou todas as linhas da tabela #TabA, exceto a linha do número 5, letra A, porque esta linha aparece na tabela #TabB.

Quando acrescentamos a tabela #TabC na query, mais uma linha deixa de aparecer:



E se tratarmos apenas a coluna Numero?



Os números 5 e 6 não são exibidos, porque eles existem na tabela #TabB, e o número 1 não é exibido, porque ele existe na tabela #TabC.

Para fechar esse post, vamos misturar tudo o que vimos até agora. Primeiro, vamos voltar ao primeiro conjunto de tabelas, e acrescentar mais duas:


E agora, utilizar os três operadores na mesma query:


Por que o resultado da query são os números 1, 2, 3, 4, 5 e 6?

O que efetivamente aconteceu aqui? Vamos analisar a query em partes, para entender o resultado exposto.

Primeiro, vamos visualizar o conteúdo de cada tabela:



Agora, vamos analisar a query em partes:



O comando INTERSECT precede UNION e EXCEPT. Então, essa parte da query equivale a:


Quando o SQL Server executa o UNION, o resultado passa a ser 1,2 3, 4, 5, 6, 9, 10. Então, o EXCEPT retira 9 e 10, deixando apenas a sequência de 1 a 6.

#UNION #INTERSECT #EXCEPT #SELECT

0 visualização