En este acertijo, vamos a aprender a reescribir una subconsulta utilizando inner joins. Conocer una subconsulta frente a un inner join puede ayudarte con las preguntas de la entrevista y los problemas de rendimiento. Aunque las subconsultas tienen habilidades únicas, hay ocasiones en las que es mejor utilizar otras construcciones SQL como las uniones.
Al leer este artículo aprenderás sobre varios tipos de subconsultas, y cómo cada una puede cambiarse a otra forma, como una unión.
Resolver rompecabezas es una gran manera de aprender SQL. No hay nada mejor que practicar lo que se ha aprendido. Una vez que hayas resuelto el puzzle, publica tu respuesta en los comentarios para que todos podamos aprender unos de otros. También discutimos el rompecabezas y más en el Grupo de Aprendizaje de SQL Esencial en Facebook. Asegúrese de encontrarnos allí!
Pregunta de rompecabezas SQL
Un remedio para la confusión de consultas…
Un compañero de trabajo acaba de aprender sobre las subconsultas y escribió algo de SQL para recuperar los nombres de los empleados y las fechas de nacimiento de la base de datos AdventureWorks. El problema es que quieren cambiarlo y ahora es difícil de leer.
¿Puedes ayudarles a simplificar el siguiente 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)
¿Qué declaración escribirías para que sea más fácil de leer, y tal vez se ejecute de manera más eficiente?
Subconsulta versus Inner Join Answer
Antes de empezar hablemos de la consulta existente… ¿qué es?
Verás que la consulta combina datos de dos tablas diferentes. Lo hace utilizando subconsultas en las cláusulas FROM y WHERE. Éstas están resaltadas en 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)
Además, verá que la cláusula WHERE de cada subconsulta restringe las filas devueltas a las que son iguales al Employee.BusinessEntityID. Esto es lo que se llama una subconsulta correlacionada.
También quiero señalar que las consultas en el FROM deben devolver un solo valor (escalar). Si no lo hacen, se lanza un error.
Como puedes imaginar, esto es peligroso, ya que puede ser difícil garantizar que una consulta devuelva como máximo una fila. En este caso sé que es seguro porque la condición de coincidencia se da entre las claves primarias de cada tabla.
Subconsulta versus Inner Join – Convirtiendo la consulta
Si yo estuviera escribiendo esta consulta utilizaría un INNER JOIN. Esta es la consulta que escribiría:
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
¿Cuál es más fácil de leer?
Esto no debería ser un gran debate, el INNER JOIN es mucho más corto, y creo que va al grano. La cláusula join habla por sí misma. Sabes que está relacionando dos tablas; mientras que, con la subconsulta, es tan aparente.
La versión INNER JOIN es más fácil de mantener.
Además, con el método de subconsulta, verás gran parte del código repetido. Esto puede no parecer un gran problema, ahora, pero si alguna vez tiene que cambiar la consulta, lo es, ya que ahora cuando hace un cambio tiene que asegurarse de hacer el mismo cambio en varios lugares.
¿SubQuery o Inner Join? ¿Cuál es más eficiente?
Aquí está el plan de consulta para la versión de subconsulta:
He resaltado el efecto de las cuatro subconsultas. Para esta declaración, cada consulta resulta en un bucle anidado. Esto no es bueno.
Significa que si tiene diez filas en dos tablas cada una, entonces necesita en promedio, iterar a través de la segunda tabla 50 veces (100/2) para cada fila en la primera para encontrar una coincidencia. Esto significa que, en lugar de que una búsqueda tome dos o tres operaciones para encontrar una coincidencia, la coincidencia podría tomar más de 100 * 50 = 500 búsquedas para encontrar.
Los bucles anidados son un hecho de la vida, pero menos es mejor.
Y aquí está la versión para el 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
Aquí se ve que sólo hay un bucle anidado. Después de observar tanto el SQL como los planes de consulta de cada conjunto de sentencias, puede ver que INNER JOIN es superior en varios aspectos; sin embargo, ¡fíjese en ese plan simplificado!
La verdadera tarea de la consulta es combinar columnas de dos tablas; esto es lo que hacen los INNER JOIN. Por supuesto, hay momentos en los que las subconsultas tienen sentido, y se pueden utilizar para hacer cosas que no se pueden hacer con los joins, pero en este caso, no tiene sentido utilizar uno.