Historia pytania:
Zagnieżdżone podzapytania pierwotnie zostały wprowadzone w SQL w celu rozszerzenia możliwości językowych i rozwiązania złożonych problemów biznesowych, które nie mogły być rozwiązane za pomocą prostych operatorów SELECT. Jednak wraz ze wzrostem objętości danych i złożoności modeli relacyjnych pojawiło się zrozumienie — nie zawsze zagnieżdżone podzapytania działają efektywnie: wiele zależy od wprowadzenia optymalizatora w konkretnej DBMS.
Problem:
Głównym wyzwaniem jest znalezienie kompromisu między czytelnością, poprawnością logiki i wydajnością. Nie zawsze zagnieżdżone podzapytania są optymalizowane do operacji join, a często przekształcają się w kosztowne pętle przeszukiwania (Nested Loops).
Rozwiązanie:
Przykład kodu:
-- Zagnieżdżone podzapytanie w SELECT (ostrożnie!) SELECT name, (SELECT COUNT(*) FROM orders WHERE orders.client_id = clients.id) AS order_count FROM clients; -- Równoważny przez JOIN (zwykle szybszy): SELECT clients.name, COUNT(orders.id) AS order_count FROM clients LEFT JOIN orders ON orders.client_id = clients.id GROUP BY clients.name;
Kluczowe cechy:
Czy zagnieżdżone podzapytanie w SELECT działa szybciej niż równoważny LEFT JOIN?
Częściej — nie. Skorelowane podzapytanie w SELECT jest wykonywane dla każdego wiersza zewnętrznego zapytania, podczas gdy JOIN jest budowany raz z indeksami dla całej tabeli.
Czy można użyć podzapytania w FROM zamiast CTE (WITH) i czy będzie różnica?
Tak, podzapytanie w FROM:**
SELECT t1.id, sub.agg FROM table1 t1 JOIN (SELECT id, MAX(val) AS agg FROM table2 GROUP BY id) sub ON t1.id = sub.id;
Jednak CTE czasami ma lepszą czytelność i może prowadzić do innej optymalizacji w planach wykonania.
Czy wszystkie zagnieżdżone podzapytania są optymalizowane do odpowiednich JOIN?
Nie. Nie wszystkie DBMS potrafią to zrobić równie dobrze, czasami zagnieżdżone podzapytanie prowadzi do przeszukiwania każdej linii, szczególnie jeśli istnieje korelacja między zewnętrznym a wewnętrznym zapytaniem.
Menadżer sprzedaży przygotował raport o klientach, licząc wewnętrznym SELECT liczbę zamówień. Czas wykonania — minuty, obciążenie serwera rosło w geometrycznej progresji.
Zalety:
Zapytanie przepisano za pomocą LEFT JOIN i grupowania.
Zalety: