Desafio SQL Server – Cadê meu JOIN?!

Achei esse desafio em um site(no qual não vou dizer agora pros espertinhos não procurarem a resposta; porém, darei todo o crédito ao responsável pelo desafio depois, ok?!), e resolvi compartilhar com vocês.

O nome do desafio é Cadê o meu JOIN?

A resposta estarei postando em breve ou comentarei quando alguém acertar! Abraço a todos os amantes do SQL Server!

Uma pessoa me apresentou uma consulta SQL que relacionava os dados de cliente com os endereços.

SELECT c.* FROM Clientes c LEFT OUTER JOIN Regioes r
ON c.regiaoId = r.regiaoId AND
r.regiaoId IS NULL

O interessante é que o plano de execução gerada não possui JOIN entre tabelas. Surge a pergunta: CADÊ MEU JOIN???

image

O problema fica mais interessante quando substituimos o LEFT OUTER JOIN por um INNER JOIN, pois o plano de execução não apresenta a leitura em nenhuma tabela.

SELECT c.* FROM Clientes c INNER JOIN Regioes r
ON c.regiaoId = r.regiaoId AND
r.regiaoId IS NULL

image

A pergunta desse Desafio Ninja é:

O que aconteceu com o Join de tabela e com a operação de Table Scan?

Fico aguardando as respostas nos comentários!

Script usado:

CREATE TABLE Regioes
(regiaoId INT PRIMARY KEY,
   local VARCHAR(100) NOT NULL)

CREATE TABLE Clientes
  (id INT,
nome VARCHAR(50),
regiaoId INT FOREIGN KEY REFERENCES Regioes(regiaoId))

INSERT Regioes VALUES (1, ‘Norte’), (2, ‘Sul’)
INSERT Clientes VALUES (1, ‘Cliente1’, 1), (2, ‘Cliente2’, 1)
GO

SELECT c.* FROM Clientes c LEFT JOIN Regioes r
ON    c.regiaoId = r.regiaoId AND
r.regiaoId IS NULL

SELECT c.* FROM Clientes c INNER JOIN Regioes r
ON    c.regiaoId = r.regiaoId AND
r.regiaoId IS NULL

Anúncios

UNION x UNION ALL

Muitas vezes vejo pessoas com dúvida sobre a diferença entre UNION e UNION ALL, apesar de ser simples a diferença.

Explicando de uma forma um pouco “grosseira”:

  • UNION realiza um DISTINCT entre os SELECTS, ou seja, os registros que tiverem informação repetida só apareceram uma vez no ResultSet
  • UNION ALL simplesmente une os SELECTS, ou seja, os registros que tiverem informação repetido apareceram no ResultSet quantas vezes eles existirem

Existem algumas regras para se usar o UNION e o UNION ALL (e são as mesmas):

  • Os ResultSet devem conter o mesmo número de colunas e devem ser do mesmo tipo (INT, NUMERIC, VARCHAR); caso contrário o SQL Server retornará um erro;
  • O nome das colunas deverá estar no primeiro SELECT e será atribuído as demais colunas;
  • A cláusula de ordenação ORDER BY só poderá ser usada após o último SELECT e ordenará todo o resultado que foi unido pelo UNION ou pelo UNION ALL; caso contrário, o SQL Server retornará um erro.

Dica de Perfomance: Se você precisa unir resultados que não podem se repetir e você conhece os resultados do SELECT e já sabem que eles não se repetem, então você deve usar o UNION ALL, pois ele não utilizará o DISTINCT entre os SELECTS o que causa um ganho de PERFOMANCE. Já se você usar o UNION o SQL Server utilizará um DISTINCT em cima de um resultado que não se repete, ou seja, consumirá recursos À toa.

Vamos ao exemplo prático:

–Declara variáveis de tabela para exemplo

DECLARE @tabela1 as TABLE(codigo int null, nome varchar(50) null)

DECLARE @tabela2 as TABLE(codigo int null, nome varchar(50) null)

 

–Insere dados na @tabela1

INSERT INTO @tabela1 VALUES

(1,‘nome1’),

(2,‘nome2’),

(3,‘nome3’),

(4,‘nome4’)

 

–Insere dados na @tabela2

INSERT INTO @tabela2 VALUES

(1,’nome1′),

(3,’nome3′),

(5,’nome5′),

(7,’nome7′)

 

–Exibe os campos da @tabela1

SELECT

                *

FROM

                @tabela1

–Exibe os campos da @tabela2    

SELECT

                *

FROM

                @tabela2

 

–Note que somente os registros do nome1 e nome3 se repetem nas tabelas

 

–Agora veja o resultado da união das duas consultas utilizando o UNION

–Os campos que possuem registros repetidos nas duas tabelas são exibidos apenas uma única vez

SELECT

                *

FROM

                @tabela1

UNION

SELECT

                *

FROM

                @tabela2

 

 

–Agora veja o resulta da união das duas consultas utilizando o UNION ALL

–Os campos que possuem registros repetidos nas duas tabelas são exibidos quantas vezes existirem nas consultas envolvidas

SELECT

                *

FROM

                @tabela1

UNION ALL

SELECT

                *

FROM

                @tabela2

 

 

 Analisando os planos de execução você pode ver porque o melhor é usar o UNION ALL no caso de você ter certeza de que os campos não vão se repetir, pois, neste caso, a consulta custa 22% a menos no UNION ALL por causa do DISTINCT (que equivale a 63% dos 35% gastos) do custo total  que é utilizado no UNION. Veja abaixo: 

Plano de Execução com UNION

 

 

Plano de Execução com UNION ALL

 

 Bom…por hoje é só. Espero que vocês tenham conseguido entender a diferença entre UNION e UNION ALL. Mais do que isso, que vocês tenham aprendido quando usar cada um deles!

Até o próximo post!