Łapka LogoŁapka Infa
🧅
Bazy Danych

Zagnieżdżone Podzapytania (Subqueries)

Jak zbudować incepcję w SQL - zapytanie w zapytaniu. Dowiedz się jak wyciągnąć np. osoby zarabiające więcej niż średnia.

Podzapytania w SQL (Subqueries)

Czasami żeby znaleźć odpowiedź na jedno pytanie, musisz najpierw zadać bazie drugie pytanie.

Wyobraź sobie zadanie: "Wyświetl imiona i nazwiska pracowników, którzy zarabiają więcej niż wynosi średnia pensja w firmie".

Nie możesz napisać wprost:

SELECT Imie, Nazwisko FROM Pracownicy WHERE Pensja > AVG(Pensja); -- TO JEST BŁĄD!

Baza zrzuci błąd, ponieważ funkcje agregujące (jak AVG) nie mogą być "ot tak" wsadzane do instrukcji WHERE.

Rozwiązaniem jest zastosowanie podzapytania (zapytania zagnieżdżonego), które najpierw wyliczy średnią z tyłu sceny, a potem podstawi ją do zapytania właściwego.

1. Podzapytanie w WHERE

Budujemy główne zapytanie i tam gdzie potrzebujemy naszej policzonej wartości, otwieramy nawias okrągły () i wsadzamy całkiem nowego SELECTa.

SELECT Imie, Nazwisko, Pensja
FROM Pracownicy
WHERE Pensja > (
    SELECT AVG(Pensja) 
    FROM Pracownicy
);

Zauważ: Baza najpierw wykonuje podzapytanie wewnątrz nawiasu (dostaje z niego wynik np. 3200), a potem podstawia to pod główny warunek: WHERE Pensja > 3200.

🗄️

Interaktywna Konsola: Podzapytanie w klauzuli WHERE

Wyszukaj pracowników, których zarobki są wyższe od średniej w całej firmie.

Symbole:

2. Podzapytanie ze zbiorem wyników (IN)

Jeśli podzapytanie wewnątrz nawiasu nie zwróci jednej konkretnej liczby (jak średnia pensja), ale zwróci całą listę/kolumnę liczb, nie możemy uzyć znaku równości = ani >, bo to nie ma sensu (czy pensja > [zbiór liczb]?).

W takim przypadku, jeśli szukamy czy dana wartość znajduje się w zwróconym zbiorze, używamy operatora IN.

Zadanie: Znajdź klientów, którzy zrobili zakupy w 2023 roku, nie używając JOIN.

SELECT Imie, Nazwisko
FROM Klienci
WHERE ID_Klienta IN (
    SELECT ID_Klienta 
    FROM Zamowienia 
    WHERE YEAR(DataZamowienia) = 2023
);

[!WARNING] Kiedy NIE używać podzapytań? Jeśli używasz IN z ciężkim podzapytaniem przy 100 tysiącach rekordów, baza potrafi "zmulic", ponieważ w skrajnych przypadkach potrafi ewaluować to podzapytanie dla każdego wiersza od nowa (choć nowsze silniki to optymalizują). W 90% przypadków operator JOIN jest szybszy i bezpieczniejszy od zagnieżdżonych podzapytań typu IN. Na maturze z informatyki i egzaminie INF.03 zbiory są jednak małe i nie ma to aż takiego znaczenia czasowego, więc rób to tak, jak Ci wygodniej!