INF.03 · Bazy danych i SQL

Podzapytania: zapytanie w zapytaniu

„Pokaż produkty droższe niż średnia cena w całym sklepie.” Żeby odpowiedzieć, potrzebujesz dwóch kroków: najpierw policzyć średnią, a potem porównać z nią każdy produkt. Dokładnie to robi podzapytanie: jedno zapytanie SQL wstawione w drugie. Panel „bestsellery” w sklepie działa na tej samej zasadzie.

  • około 35 minut
  • podzapytania w WHERE
  • IN · NOT IN · operatory

Po tej lekcji: napiszesz zapytanie, w którym wynik jednego SELECT jest warunkiem drugiego, i przewidzisz, w jakiej kolejności baza je wykona.

1 · Idea

Podzapytanie liczy się najpierw

Podzapytanie stoi w nawiasie i baza wykonuje je jako pierwsze. Jego wynik trafia do zapytania zewnętrznego. Najczęściej pojawia się w WHERE.

Rodzaj operatora zależy od tego, co zwraca podzapytanie: pojedynczą wartość (wtedy =, >, <), listę wartości (wtedy IN lub NOT IN) albo samą informację, czy coś zwróciło (wtedy EXISTS).

podzapytania.sqlsql
-- produkty droższe niż średnia cena wszystkich produktów
SELECT nazwa, cena FROM Produkty
WHERE cena > (SELECT AVG(cena) FROM Produkty);

-- klienci, którzy choć raz coś zamówili
SELECT imie, nazwisko FROM Klienci
WHERE id_klienta IN (SELECT id_klienta FROM Zamowienia);
  1. Pierwsze zapytanie w nawiasie jest jedna liczba (średnia cena), więc używasz operatora >.
  2. Drugie zapytanie w nawiasie jest lista numerów klientów, więc używasz IN.

Laboratorium · ćwiczenie w przeglądarce, do którego odsyłają rozgrzewki na końcu lekcji

2 · Sprawdź na danych

Co baza liczy najpierw, a co potem?

Prawdziwe produkty, klienci i zamówienia ze sklepu muzycznego. W pierwszej zakładce zmieniaj funkcję i operator, w drugiej wybierz miasto oraz IN lub NOT IN. Każdy krok pokazuje, co baza robi po kolei.

Ta interakcja wymaga włączonego JavaScriptu.

Sprawdź przypadek skrajny: operator = z funkcją AVG zwykle nic nie zwraca, bo żadna cena nie jest dokładnie równa średniej. Pusty wynik to poprawny wynik, a nie błąd.

3 · Zanim się pomylisz

Trzy pomyłki w podzapytaniach

Komunikaty pochodzą z prawdziwej bazy.

Operator = z podzapytaniem, które zwraca wiele wierszy
Tak nie
SELECT nazwa FROM Produkty
WHERE cena = (SELECT cena FROM Produkty);

Błąd: Subquery returns more than 1 row. Nawias zwraca dziesięć cen, a operator = potrafi porównać tylko z jedną.

Tak
SELECT nazwa FROM Produkty
WHERE cena IN (SELECT cena FROM Produkty);

Gdy podzapytanie może zwrócić kilka wartości, użyj IN zamiast =.

IN zamiast NOT IN
Tak nie
-- klienci, którzy NIE złożyli zamówień
SELECT imie FROM Klienci
WHERE id_klienta IN (SELECT id_klienta FROM Zamowienia);

Dostajesz klientów, którzy złożyli zamówienie, czyli dokładnie odwrotność tego, o co pytano.

Tak
SELECT imie FROM Klienci
WHERE id_klienta NOT IN (SELECT id_klienta FROM Zamowienia);

W tej bazie każdy klient zamawiał, więc poprawny wynik jest pusty (0 wierszy). To nie błąd, to wynik.

Podzapytanie w podzapytaniu w podzapytaniu
Tak nie
SELECT nazwa FROM Produkty WHERE id_produktu IN (
  SELECT id_produktu FROM Zamowienia WHERE id_klienta IN (
    SELECT id_klienta FROM Klienci WHERE miasto IN (
      SELECT miasto FROM Klienci WHERE imie = 'Jan')));

Zapytanie działa, ale jest bardzo trudne do przeczytania i sprawdzenia.

Tak
SELECT DISTINCT p.nazwa
FROM Produkty p
JOIN Zamowienia z ON z.id_produktu = p.id_produktu
JOIN Klienci k ON k.id_klienta = z.id_klienta
WHERE k.miasto = 'Dzialdowo';

Przy kilku poziomach często czytelniejszy jest JOIN albo rozbicie problemu na dwa osobne zapytania.

4 · Sprawdź sam siebie

Zanim uznasz podzapytanie za poprawne

Podzapytania często pojawiają się w trudniejszych zadaniach praktycznych, gdzie trzeba połączyć warunek z wynikiem innego zapytania.

Podsumowanie

Co warto zapamiętać

  1. Podzapytanie stoi w nawiasie i wykonuje się jako pierwsze.
  2. Jedna wartość: =, >, <. Lista wartości: IN lub NOT IN.
  3. = z podzapytaniem zwracającym wiele wierszy kończy się błędem.
  4. Pusty wynik jest poprawnym wynikiem.
  5. Przy głębokim zagnieżdżeniu często lepszy jest JOIN.

Dalej na swoim koncie

Rozgrzewki, quiz i zadania są w biurku ucznia.

Teoria jest otwarta dla wszystkich. Żeby rozwiązywać zadania, zapisywać szkice i widzieć swój postęp, zaloguj się.

Zaloguj się →
Źródła i dalsza nauka