W tej zagadce dowiemy się, jak przepisać podzapytanie za pomocą wewnętrznych złączeń. Wiedza na temat podzapytania w porównaniu z wewnętrznym złączeniem może pomóc ci w pytaniach podczas rozmowy kwalifikacyjnej i problemach z wydajnością. Chociaż podzapytania mają unikalne możliwości, są chwile, kiedy lepiej jest użyć innych konstrukcji SQL, takich jak złączenia.
Czytając ten artykuł dowiesz się o kilku typach podzapytań i jak każde z nich może być zamienione na inną formę, taką jak złączenie.
Rozwiązywanie zagadek jest świetnym sposobem na naukę SQL. Nic nie pobije praktyki tego, czego się nauczyłeś. Kiedy już rozwiążesz zagadkę, opublikuj swoją odpowiedź w komentarzach, abyśmy wszyscy mogli uczyć się od siebie nawzajem. Dyskutujemy również o zagadkach i nie tylko w grupie Essential SQL Learning Group na Facebooku. Znajdź nas tam!
Pytanie o zagadkę SQL
Zapobieganie zamieszaniu związanemu z zapytaniami…
Współpracownik właśnie dowiedział się o podzapytaniach i napisał trochę kodu SQL, aby pobrać nazwiska pracowników i daty urodzenia z bazy danych AdventureWorks. Problem w tym, że chce go zmienić i teraz jest trudny do odczytania!
Czy możesz pomóc mu uprościć poniższy 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)
Jakie oświadczenie napisałbyś, aby uczynić go łatwiejszym do odczytania i być może działającym bardziej wydajnie?
Subquery versus Inner Join Odpowiedź
Zanim zaczniemy, porozmawiajmy o istniejącym zapytaniu… co to jest?
Zobaczysz, że zapytanie łączy dane z dwóch różnych tabel. Robi to za pomocą podzapytań zarówno w klauzuli FROM jak i WHERE. Są one zaznaczone poniżej na niebiesko.
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)
Widzisz również, że klauzula WHERE każdego podzapytania ogranicza zwracane wiersze do tych, które są równe Employee.BusinessEntityID. To jest to, co ludzie nazywają skorelowanym podzapytaniem.
Chciałbym również zauważyć, że zapytania w FROM muszą zwracać pojedynczą wartość (skalar). Jeśli nie, wtedy błąd jest rzucany.
Jak możesz sobie wyobrazić, jest to niebezpieczne, ponieważ może być trudno zagwarantować, że zapytanie zwróci co najwyżej jeden wiersz. Wiem, że w tym przypadku jestem bezpieczny, ponieważ warunek dopasowania występuje pomiędzy kluczami głównymi każdej z tabel.
Subquery versus Inner Join – Konwersja zapytania
Gdybym pisał to zapytanie, użyłbym INNER JOIN. Oto zapytanie, które bym napisał:
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
Które z nich jest łatwiejsze do przeczytania?
Nie powinno to być przedmiotem debaty, INNER JOIN jest znacznie krótsze i myślę, że do rzeczy. Klauzula join mówi sama za siebie. Wiesz, że odnosi się do dwóch tabel razem; podczas gdy z podzapytaniem, jest to tak pozorne.
Wersja INNER JOIN jest łatwiejsza do utrzymania.
Również, z metodą podzapytania, zobaczysz wiele powtarzającego się kodu. To może nie wydawać się wielkim problemem, teraz, ale jeśli kiedykolwiek będziesz musiał zmienić zapytanie, to będzie, ponieważ teraz, kiedy dokonujesz zmiany, musisz być pewien, że dokonujesz tej samej zmiany w kilku miejscach.
SubQuery or Inner Join? Which is More Efficient?
Tutaj znajduje się plan zapytania dla wersji z podzapytaniem:
Podkreśliłem efekt czterech podzapytań. Dla tego zestawienia, każde zapytanie powoduje powstanie zagnieżdżonej pętli. To nie jest dobre.
To oznacza, że jeśli masz dziesięć wierszy w dwóch tabelach każdy, to musisz średnio, iterować przez drugą tabelę 50 razy (100/2) dla każdego wiersza w pierwszej, aby znaleźć dopasowanie. Oznacza to, że zamiast wyszukiwania trwającego dwie lub trzy operacje w celu znalezienia meczu, mecz może zająć w górę 100 * 50 = 500 poszukiwań, aby znaleźć.
Pętle zagnieżdżone są faktem, ale mniej jest lepsze.
A oto wersja dla 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
Widzisz, że jest tylko jedna pętla zagnieżdżona. Na pewno jest to lepsze niż cztery.
Po obserwacji zarówno SQL jak i planów zapytań dla każdego zestawu poleceń można zauważyć, że INNER JOIN jest lepszy na kilka sposobów; jednakże, sprawdź ten uproszczony plan!
Prawdziwym zadaniem zapytania jest połączenie kolumn z dwóch tabel; to jest to, w czym INNER JOINS przoduje. Jasne, są chwile, kiedy podzapytania mają sens i mogą być używane do robienia rzeczy, których nie można zrobić za pomocą złączeń, ale w tym przypadku, nie ma sensu używać jednego z nich.