Lekcja 9 – Podzapytania (Subqueries)

W tej lekcji zajmiemy się jednym z bardziej zaawansowanych zagadnień SQL, jakim są podzapytania (ang. subqueries). Podzapytanie to zapytanie SQL umieszczone wewnątrz innego zapytania. Jest to bardzo użyteczne narzędzie, gdy chcesz wykonywać bardziej złożone operacje na danych lub uzyskać dodatkowe informacje, które są wynikiem innego zapytania. Podzapytania mogą być używane w różnych miejscach w zapytaniach SQL, takich jak klauzula WHERE, SELECT, FROM oraz HAVING.

Podzapytania dzielą się na dwie główne kategorie:

  1. Podzapytania skalarne – zwracają pojedynczą wartość.
  2. Podzapytania zwracające wiele rekordów – zwracają wiele wartości, które mogą być przetwarzane przez zewnętrzne zapytanie.

Kiedy używać podzapytań?

Podzapytania są przydatne, gdy:

  • Chcesz wyciągnąć dane, które zależą od wyników innego zapytania.
  • Potrzebujesz filtrować wyniki na podstawie wartości, które nie są dostępne w prostym zapytaniu.
  • Chcesz przeprowadzić operacje na danych z kilku zapytań jednocześnie.

Podzapytania w klauzuli WHERE

Najczęściej podzapytania są używane w klauzuli WHERE, aby filtrować wyniki na podstawie wyników innego zapytania. Podzapytanie działa jak dynamiczny filtr, który najpierw pobiera dane z wewnętrznego zapytania, a następnie te dane są używane w zapytaniu głównym.

Składnia:

SELECT kolumna1, kolumna2
FROM tabela
WHERE kolumna IN (SELECT kolumna_wewnetrzna FROM inna_tabela WHERE warunek);

Przykład: Znajdź wszystkich użytkowników, którzy złożyli zamówienie o wartości większej niż 100.

SELECT Imie, Nazwisko
FROM Uzytkownicy
WHERE ID IN (SELECT User_ID FROM Zamowienia WHERE Wartosc > 100);

W tym przykładzie zapytanie wewnętrzne (podzapytanie) wybiera wszystkich użytkowników, którzy mają zamówienia o wartości większej niż 100, a zapytanie zewnętrzne zwraca dane o tych użytkownikach.

Podzapytania w klauzuli SELECT

Podzapytania mogą być również używane w klauzuli SELECT, aby zwracać dodatkowe dane jako część wyników głównego zapytania. Jest to przydatne, gdy chcesz uzyskać dodatkowe informacje związane z danym rekordem.

Składnia:

SELECT kolumna1, (SELECT funkcja_agregujaca(kolumna2) FROM inna_tabela WHERE warunek) AS alias
FROM tabela;

Przykład: Wyświetl imiona i nazwiska użytkowników wraz z ich łączną liczbą zamówień.

SELECT Imie, Nazwisko, (SELECT COUNT(*) FROM Zamowienia WHERE Zamowienia.User_ID = Uzytkownicy.ID) AS liczba_zamowien
FROM Uzytkownicy;

W tym przypadku podzapytanie w klauzuli SELECT zlicza liczbę zamówień dla każdego użytkownika i zwraca wynik jako dodatkową kolumnę w wynikach głównego zapytania.

Podzapytania w klauzuli FROM

Podzapytania w klauzuli FROM są używane, gdy potrzebujemy traktować wynik zapytania jako tabelę tymczasową, którą możemy dalej przetwarzać. Jest to szczególnie przydatne w sytuacjach, gdy wynik zapytania wymaga dalszej manipulacji, np. dodatkowego filtrowania czy grupowania.

Składnia:

SELECT kolumna1, kolumna2
FROM (SELECT kolumna_wewnetrzna1, kolumna_wewnetrzna2 FROM tabela WHERE warunek) AS alias
WHERE warunek_dodatkowy;

Przykład: Pokaż użytkowników, którzy mają łącznie więcej niż 5 zamówień, korzystając z podzapytania w FROM.

SELECT Imie, Nazwisko
FROM (SELECT User_ID, COUNT(*) AS liczba_zamowien FROM Zamowienia GROUP BY User_ID) AS ZamowieniaGrupowane
JOIN Uzytkownicy ON Uzytkownicy.ID = ZamowieniaGrupowane.User_ID
WHERE liczba_zamowien > 5;

W tym przykładzie podzapytanie w klauzuli FROM grupuje zamówienia według użytkownika i liczy ich liczbę. Wynik tego podzapytania jest następnie używany w zapytaniu głównym, aby zwrócić dane użytkowników, którzy mają więcej niż 5 zamówień.

Podzapytania skorelowane (Correlated Subqueries)

Podzapytania skorelowane to bardziej zaawansowane typy podzapytań, w których zapytanie wewnętrzne jest zależne od danych z zapytania zewnętrznego. W takich przypadkach podzapytanie jest wykonywane osobno dla każdego rekordu z zapytania zewnętrznego.

Składnia:

SELECT kolumna1
FROM tabela1 AS zewnetrzna
WHERE kolumna2 > (SELECT AVG(kolumna_wewnetrzna) FROM tabela2 AS wewnetrzna WHERE wewnetrzna.kolumna_wspolna = zewnetrzna.kolumna_wspolna);

Przykład: Pokaż wszystkich użytkowników, których zamówienia mają wartość większą niż średnia wartość zamówień dla tego użytkownika.

SELECT Imie, Nazwisko
FROM Uzytkownicy
WHERE EXISTS (SELECT * FROM Zamowienia WHERE Zamowienia.User_ID = Uzytkownicy.ID AND Zamowienia.Wartosc > (SELECT AVG(Wartosc) FROM Zamowienia WHERE Zamowienia.User_ID = Uzytkownicy.ID));

W tym przykładzie podzapytanie skorelowane oblicza średnią wartość zamówień dla każdego użytkownika i porównuje ją z wartością każdego zamówienia.

Podzapytania w klauzuli HAVING

Klauzula HAVING jest używana do filtrowania grup po zastosowaniu GROUP BY. Podzapytania w klauzuli HAVING pozwalają na dodatkową filtrację danych grupowanych, na podstawie wyników innych zapytań.

Przykład: Znajdź użytkowników, którzy złożyli więcej zamówień niż wynosi średnia liczba zamówień na użytkownika.

SELECT User_ID, COUNT(*) AS liczba_zamowien
FROM Zamowienia
GROUP BY User_ID
HAVING COUNT(*) > (SELECT AVG(liczba_zamowien) FROM (SELECT User_ID, COUNT(*) AS liczba_zamowien FROM Zamowienia GROUP BY User_ID) AS Podzapytanie);

W tym przykładzie wewnętrzne podzapytanie oblicza średnią liczbę zamówień na użytkownika, a klauzula HAVING używa tej wartości, aby pokazać tylko tych użytkowników, którzy mają więcej zamówień niż wynosi średnia.

Wydajność podzapytań

Choć podzapytania są potężnym narzędziem, mogą negatywnie wpływać na wydajność bazy danych, zwłaszcza w przypadku dużych zbiorów danych. Dlatego warto rozważyć alternatywne podejścia, takie jak używanie JOIN lub przekształcanie podzapytań na widoki lub tabele tymczasowe, które mogą być bardziej wydajne w przetwarzaniu skomplikowanych operacji.

Podsumowanie

Podzapytania są potężnym narzędziem w SQL, które pozwala na wykonywanie bardziej złożonych zapytań i operacji na danych. Mogą być używane w różnych miejscach w zapytaniach, takich jak klauzula WHERE, SELECT, FROM i HAVING. Podzapytania skorelowane dodatkowo zwiększają możliwości manipulowania danymi, ponieważ pozwalają na wykonywanie zapytań zależnych od wyników zapytań zewnętrznych. Choć podzapytania są bardzo elastyczne, należy pamiętać o ich potencjalnym wpływie na wydajność, zwłaszcza w dużych bazach danych.

W kolejnych lekcjach omówimy indeksowanie i optymalizację zapytań SQL, co pozwoli na lepsze zrozumienie, jak zwiększyć efektywność działania zapytań.

Gratulacje! Ukończyłeś lekcję 9.
Przejdź teraz do lekcji 10 >> Indeksy w bazach danych


Spis Treści - darmowy kurs SQL


Wprowadzenie: Czym jest baza danych?
Lekcja 1: Instalacja dedykowanego środowiska dla SQL
Lekcja 2: Tworzenie bazy danych
Lekcja 3: Tworzenie tabel w SQL
Lekcja 4: Wstawianie danych do bazy danych SQL
Lekcja 5: Pobieranie danych z bazy danych SQL
Lekcja 6: Aktualizacja i usuwanie danych SQL
Lekcja 7: Operacje na danych (JOIN)
Lekcja 8: Funkcje agregujące i grupowanie danych (GROUP BY)
Lekcja 9: Podzapytania (Subqueries)
Lekcja 10: Indeksy w bazach danych
Lekcja 11: Optymalizacja zapytań SQL
Lekcja 12: Transakcje w bazach danych
Lekcja 13: Zarządzanie blokadami (Locks) i dostępem do danych
Lekcja 14: Replikacja danych w bazach danych
Lekcja 15: Partycjonowanie danych SQL
Lekcja 16: Widoki (Views) w bazach danych
Lekcja 17: Procedury składowane (Stored Procedures) i funkcje w SQL
Lekcja 18: Wyzwalacze (Triggers) w bazach danych
Lekcja 19: Zaawansowane indeksowanie w bazach danych
Lekcja 20: Narzędzia do zarządzania dużymi danymi (Big Data) w SQL
Lekcja 21: Bezpieczeństwo baz danych


Dodatki: 
- Spis najważniejszych funkcji SQL