Подзапросы / CTEСредний
Подзапрос (Subquery)
SELECT внутри другого SQL выражения. Может быть в FROM, WHERE, HAVING или SELECT.
Синтаксис
-- В WHERE:
SELECT * FROM t WHERE col IN (SELECT col FROM t2);
-- В FROM:
SELECT * FROM (SELECT ...) sub;Объяснение
Подзапросы бывают:
- Некоррелированные: выполняются один раз, независимо от внешнего запроса
- Коррелированные: ссылаются на внешний запрос, выполняются для каждой строки — потенциально медленно
В большинстве случаев современные оптимизаторы могут переписать подзапрос как JOIN. Но не всегда — смотри EXPLAIN.
Пример
-- Некоррелированный (быстро — один раз)
SELECT * FROM products
WHERE category_id IN (SELECT id FROM categories WHERE is_active = true);
-- Коррелированный (медленно — для каждой строки)
SELECT name,
(SELECT COUNT(*) FROM orders WHERE user_id = u.id) AS orders
FROM users u;Связанные термины
Анекдоты по теме
Пользователь: — Почему мой запрос ничего не вернул? DBA: — А ты проверил регистр? Пользователь: — Да. DBA: — А пробелы? Пользователь: — Да. DBA: — А кодировку? Пользователь: — О господи...
— Мой запрос работает 10 секунд. Как ускорить? — Покажи EXPLAIN ANALYZE. — Вот: Seq Scan, cost=0..999999. — Индекс. — Уже 0.5 секунды. — Теперь смотри на остальные узлы.
— Мой EXPLAIN показывает Seq Scan. — Добавь индекс. — Добавил. Всё равно Seq Scan. — Сколько строк в таблице? — 50. — Оптимизатор умнее тебя. При 50 строках индекс медленнее.