Neste puzzle, vamos aprender a reescrever uma subconsulta usando as uniões interiores. Saber sobre uma subquisição versus união interna pode ajudá-lo com perguntas de entrevista e questões de desempenho. Embora subconsultas tenham habilidades únicas, há momentos em que é melhor usar outras construções SQL como joins.
Lendo este artigo você aprenderá sobre vários tipos de subconsultas, e como cada uma pode ser mudada para outra forma, como um join.
Solver quebra-cabeças é uma ótima maneira de aprender SQL. Nada é melhor do que praticar o que você aprendeu. Depois de ter descoberto o puzzle, coloque sua resposta nos comentários para que todos nós possamos aprender uns com os outros. Também discutimos enigmas e muito mais no Essential SQL Learning Group no Facebook. Certifique-se de nos encontrar lá!
SQL Puzzle Question
Um remédio para confusão de consultas…
Um colega de trabalho acabou de aprender sobre subconsultas e escreveu algum SQL para recuperar nomes de funcionários e datas de nascimento do banco de dados AdventureWorks. O problema é que eles querem alterá-lo e agora é difícil de ler!
Pode ajudá-los a simplificar o seguinte SQL?
SELECT E.HireDate, (SELECT FirstName FROM Person.Person P1 WHERE P1.BusinessEntityID = E.BusinessEntityID), (SELECT LastName FROM Person.Person P2 WHERE P2.BusinessEntityID = E.BusinessEntityID), E.BirthDateFROM HumanResources.Employee EWHERE (SELECT PersonType FROM Person.Person T WHERE T.BusinessEntityID = E.BusinessEntityID) = 'EM'ORDER BY HireDate, (SELECT FirstName FROM Person.Person P1 WHERE P1.BusinessEntityID = E.BusinessEntityID)
Que Declaração você escreveria para facilitar a leitura, e talvez executar mais eficientemente?
Subquery versus Inner Join Answer
Antes de começarmos a falar sobre a consulta existente… o que é?
Verá que a consulta combina dados de duas tabelas diferentes. Ela está fazendo isso usando subconsultas tanto nas cláusulas DE e ONDE. Estas estão destacadas abaixo em Azul.
SELECT E.HireDate, (SELECT FirstName FROM Person.Person P1 WHERE P1.BusinessEntityID = E.BusinessEntityID), (SELECT LastName FROM Person.Person P2 WHERE P2.BusinessEntityID = E.BusinessEntityID), E.BirthDateFROM HumanResources.Employee EWHERE (SELECT PersonType FROM Person.Person T WHERE T.BusinessEntityID = E.BusinessEntityID) = 'EM'ORDER BY HireDate, (SELECT FirstName FROM Person.Person P1 WHERE P1.BusinessEntityID = E.BusinessEntityID)
Ainda, você verá que cada cláusula WHERE da subconsulta está restringindo as linhas retornadas àquelas iguais ao Employee.BusinessEntityID. Isto é o que as pessoas chamam de subconsulta correlata.
Eu também quero ressaltar que as consultas no FROM devem retornar um único valor (escalar). Se não retornarem, então um erro é lançado.
Como você pode imaginar, isto é perigoso, pois pode ser difícil garantir o retorno de uma consulta no máximo uma linha. Eu sei que neste caso eu sei que é seguro, pois a condição de correspondência ocorre entre as chaves primárias de cada tabela.
Subquery versus Inner Join – Convertendo a consulta
Se eu estivesse escrevendo esta consulta eu usaria um INNER JOIN. Aqui está a consulta que eu escreveria:
SELECT E.HireDate, P.FirstName, P.LastName, E.BirthDateFROM HumanResources.Employee E INNER JOIN Person.Person P ON P.BusinessEntityID = E.BusinessEntityIDWHERE P.PersonType = 'EM'ORDER BY E.HireDate, P.FirstName
O que é mais fácil de ler?
Isso não deve ser um grande debate, o INNER JOIN é muito mais curto, e eu acho que ao ponto. A cláusula de adesão fala por si. Você sabe que ela está relacionando duas tabelas juntas; enquanto que, com a subconsulta, ela é tão aparente.
A versão INNER JOIN é mais fácil de manter.
Também, com o método de subconsulta, você verá muito do código ser repetido. Isto pode não parecer uma grande coisa, mas se alguma vez tiver de alterar a consulta, é, como agora quando faz uma alteração precisa de ter a certeza de fazer a mesma alteração em vários locais.
SubQuery ou Inner Join? O que é mais eficiente?
Aqui está o plano de consulta para a versão da subconsulta:
Eu realcei o efeito das quatro subconsultas. Para esta afirmação, cada consulta resulta em um loop aninhado. Estas não são boas.
Significa que se você tem dez linhas em duas tabelas cada, então você precisa em média, iterar através da segunda tabela 50 vezes (100/2) para cada linha na primeira para encontrar uma correspondência. Isto significa que, em vez de uma procura, em duas ou três operações para encontrar uma correspondência, a correspondência pode levar para cima de 100 * 50 = 500 procura encontrar.
Laçadas aninhadas são um facto da vida, mas menos é melhor.
E aqui está a versão para o INNER JOIN:
SET SHOWPLAN_ALL ONSELECT E.HireDate, P.FirstName, P.LastName, E.BirthDateFROM HumanResources.Employee E INNER JOIN Person.Person P ON P.BusinessEntityID = E.BusinessEntityIDWHERE P.PersonType = 'EM'ORDER BY E.HireDate, P.FirstName
Aqui você vê que há apenas uma laçada aninhada. Com certeza isso é melhor que quatro.
Depois de observar os planos SQL e de consulta para cada conjunto de instruções você pode ver que INNER JOIN é superior de várias maneiras; no entanto, verifique esse plano simplificado!
A verdadeira tarefa da consulta é combinar colunas de duas tabelas; é nisso que INNER JOINS se destaca. Claro, existem subconsultas de tempo que fazem sentido, e podem ser usadas para fazer coisas que você não pode com joins, mas neste caso, não faz sentido usar um.