Zapytania zagnieżdżone w klauzuli WHERE – podzapytanie zwracające pojedynczą wartość oraz operatory IN i NOT IN dla listy wyników.
Czasem warunek, którego potrzebujesz, sam wymaga odpytania bazy. „Uczniowie ze średnią powyżej średniej całej szkoły" – żeby to sprawdzić, trzeba najpierw tę średnią policzyć. Podzapytanie pozwala zrobić obie rzeczy w jednym poleceniu: zapytanie wewnętrzne liczy potrzebną wartość, a zewnętrzne używa jej jako warunku.
Podzapytanie zapisuje się w nawiasie i wykonuje się ono jako pierwsze. Dopiero jego wynik trafia do warunku zapytania zewnętrznego. Czytając cudze zapytanie z podzapytaniem, zacznij więc od środka – od nawiasu – a nie od początku linii.
Podzapytanie zwracające jedną wartość. Jeśli wewnętrzne zapytanie zwraca dokładnie jedną liczbę (typowo przez AVG, MAX czy COUNT), można je porównać zwykłym operatorem: WHERE srednia > (SELECT AVG(srednia) FROM uczniowie). Baza podstawia policzoną wartość w miejsce nawiasu i dalej działa to jak zwykły warunek WHERE.
Podzapytanie zwracające listę. Częściej wynik wewnętrzny to cała kolumna wartości – wtedy zwykłe = nie zadziała, bo nie da się porównać jednej wartości z listą. Służy do tego operator IN: sprawdza, czy wartość znajduje się gdziekolwiek na tej liście. WHERE id IN (SELECT uczen_id FROM oceny) znaczy „uczniowie, których numer występuje wśród numerów w tabeli ocen".
NOT IN działa odwrotnie – zwraca wiersze, których na liście nie ma. To najprostszy sposób na pytanie „kto nie ma ani jednej oceny", na które złączenie wewnętrzne z definicji nie potrafi odpowiedzieć, bo pomija wiersze bez dopasowania.
Podzapytanie a złączenie. Sporo zadań da się rozwiązać oboma sposobami i oba bywają uznawane. Różnica jest w tym, co dostajesz na wyjściu: złączenie dokłada kolumny z drugiej tabeli do wyniku, a podzapytanie z IN służy tylko do odsiania wierszy – kolumn z tabeli wewnętrznej w wyniku nie zobaczysz. Jeśli zadanie prosi o pokazanie danych z obu tabel, potrzebne jest złączenie. Jeśli tylko o wskazanie wierszy spełniających warunek – podzapytanie jest zwykle czytelniejsze.
Uwaga na NOT IN i puste wartości. Jeżeli lista zwrócona przez podzapytanie zawiera choć jedną wartość pustą (NULL), NOT IN potrafi zwrócić pustą tabelę, mimo że intuicja podpowiada coś innego. To znany zaskakujący przypadek – przy NOT IN warto upewnić się, że kolumna w podzapytaniu nie ma pustych pól.
-- Podzapytanie zwraca jedną liczbę: średnią ze wszystkich uczniów (4.21) SELECT nazwisko, srednia FROM uczniowie WHERE srednia > (SELECT AVG(srednia) FROM uczniowie)
| nazwisko | srednia |
|---|---|
| Kowalska | 4.75 |
| Wiśniewski | 5.10 |
-- Podzapytanie zwraca listę numerów - porównujemy operatorem IN SELECT nazwisko FROM uczniowie WHERE id IN ( SELECT uczen_id FROM oceny WHERE przedmiot = 'informatyka' )
| nazwisko |
|---|
| Kowalska |
| Nowak |
| Wiśniewski |
-- NOT IN odpowiada na pytanie, na które INNER JOIN nie potrafi SELECT nazwisko FROM uczniowie WHERE id NOT IN (SELECT uczen_id FROM oceny)
| nazwisko |
|---|
| Zając |
| Dąbrowski |
Zacznij od ustalenia, co ma zwrócić podzapytanie: jedną wartość czy listę. To rozstrzyga, jakiego operatora użyć. Porównanie = z podzapytaniem zwracającym wiele wierszy kończy się błędem – i odwrotnie, IN z jedną wartością zadziała, ale jest mylące dla czytającego.
Częsta pułapka: podzapytanie liczące AVG na tej samej tabeli, co zapytanie zewnętrzne. To jest poprawne i działa – wewnętrzne SELECT AVG(srednia) FROM uczniowie liczy średnią z całej tabeli, niezależnie od tego, że zewnętrzne zapytanie zaraz ją zawęzi. Uczniowie często zakładają błędnie, że warunek zewnętrzny wpływa też na podzapytanie.
Sprawdzaj wynik na danych z arkusza. Podzapytania rzadko wywalają się błędem składni – częściej zwracają coś, co wygląda poprawnie, ale odpowiada na nieco inne pytanie niż to z polecenia.
Tak, choć na maturze zdecydowanie najczęściej pojawia się w WHERE. Podzapytanie w FROM tworzy tabelę tymczasową, na której działa zapytanie zewnętrzne, a w SELECT – dokłada do wyniku wartość liczoną osobno dla każdego wiersza.
Formalnie wiele, praktycznie – im mniej, tym lepiej. Zapytanie z trzema poziomami nawiasów jest bardzo trudne do sprawdzenia wzrokiem. Jeśli zadanie prowadzi w tę stronę, warto rozważyć złączenie zamiast kolejnego zagnieżdżenia.
Zależy od tego, czy odwołuje się do zapytania zewnętrznego. Podzapytanie niezależne – jak SELECT AVG(srednia) FROM uczniowie – baza liczy raz i podstawia gotowy wynik. Podzapytanie skorelowane, czyli używające kolumny z zapytania zewnętrznego, musi zostać policzone osobno dla każdego sprawdzanego wiersza.
Zagadnienia z tego samego obszaru matury – warto je powtórzyć razem: