| Typ | Zwraca | Gdzie używane |
|---|---|---|
| Skalarne | Jedną wartość (1 wiersz, 1 kolumna) | WHERE, SELECT, HAVING |
| Wierszowe | Jeden wiersz, wiele kolumn | WHERE z operatorem wiersza |
| Tabelaryczne | Wiele wierszy i kolumn | IN, NOT IN, FROM (derived table) |
| Korelowane | Dla każdego wiersza zewnętrznego osobno | WHERE EXISTS, WHERE col = (subq) |
-- Skalarne: produkty droższe od średniej ceny SELECT nazwa, cena FROM produkty WHERE cena > (SELECT AVG(cena) FROM produkty); -- Tabelaryczne z IN: klienci, którzy złożyli zamówienie SELECT imie, nazwisko FROM klienci WHERE id_klienta IN ( SELECT DISTINCT id_klienta FROM zamowienia );
-- NOT IN: klienci BEZ żadnego zamówienia SELECT imie, nazwisko FROM klienci WHERE id_klienta NOT IN ( SELECT DISTINCT id_klienta FROM zamowienia WHERE id_klienta IS NOT NULL -- UWAGA: NOT IN z NULL daje zawsze FALSE! ); -- EXISTS: czy klient złożył co najmniej 1 zamówienie? SELECT k.imie, k.nazwisko FROM klienci k WHERE EXISTS ( SELECT 1 FROM zamowienia z WHERE z.id_klienta = k.id_klienta -- korelacja z zewnętrznym! ); -- NOT EXISTS: klienci bez zamówień (bezpieczniejsze niż NOT IN) SELECT k.imie, k.nazwisko FROM klienci k WHERE NOT EXISTS ( SELECT 1 FROM zamowienia z WHERE z.id_klienta = k.id_klienta );
NOT IN zawsze zwróci pusty wynik. Używaj NOT EXISTS lub filtruj NULL: WHERE id_klienta IS NOT NULL.
-- Podzapytanie w FROM (derived table / tabela pochodna) SELECT kategoria, srednia_cena FROM ( SELECT kategoria, AVG(cena) AS srednia_cena FROM produkty GROUP BY kategoria ) AS statystyki -- alias jest wymagany! WHERE srednia_cena > 300; -- Podzapytanie w SELECT (skalarne) SELECT k.imie, k.nazwisko, (SELECT COUNT(*) FROM zamowienia z WHERE z.id_klienta = k.id_klienta) AS ile_zamowien FROM klienci k;
Które z poniższych zapytań zawiera skalarne podzapytanie?
Które stwierdzenie o wydajności EXISTS vs IN jest prawdziwe?
Tabele: klienci(id_klienta, imie, nazwisko), zamowienia(id_zamowienia, id_klienta, data). Napisz zapytanie zwracające klientów, którzy NIGDY nie złożyli zamówienia:
IN (subquery) sprawdza czy wartość jest w wyniku podzapytaniaNOT EXISTS jest bezpieczniejszy niż NOT IN gdy mogą być wartości NULLFROM (SELECT ...) AS alias