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).
-- 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);
- Pierwsze zapytanie w nawiasie jest jedna liczba (średnia cena), więc używasz operatora
>. - 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.
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
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ą.
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
-- 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.
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
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.
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ć
- Podzapytanie stoi w nawiasie i wykonuje się jako pierwsze.
- Jedna wartość:
=,>,<. Lista wartości:INlubNOT IN. =z podzapytaniem zwracającym wiele wierszy kończy się błędem.- Pusty wynik jest poprawnym wynikiem.
- 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ę →