Подзапросы / CTEСредний
EXISTS
Проверяет, возвращает ли подзапрос хотя бы одну строку — не важно сколько, важен сам факт.
Синтаксис
SELECT ... WHERE EXISTS (SELECT 1 FROM ... WHERE ...);Объяснение
EXISTS возвращает TRUE, если подзапрос нашёл хотя бы одну строку, и останавливается на первой найденной (short-circuit) — не читает весь результат, в отличие от IN. На больших подзапросах это заметно быстрее.
Внутри EXISTS обычно пишут SELECT 1 — конкретная выбираемая колонка не имеет значения, важен только факт существования строки.
Пример
-- Пользователи, сделавшие хотя бы один заказ
SELECT * FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);Связанные термины
Анекдоты по теме
— Мой запрос работает 10 секунд. Как ускорить? — Покажи EXPLAIN ANALYZE. — Вот: Seq Scan, cost=0..999999. — Индекс. — Уже 0.5 секунды. — Теперь смотри на остальные узлы.
— Доктор, у меня SELECT в SELECT. — Это подзапрос. Неопасно, если не вложен в WHERE. — А если в WHERE? — Тогда держитесь. А если коррелированный? — Тогда пишите завещание.
— Что такое Bitmap Scan? — Промежуточный шаг. PostgreSQL сначала собирает битмап нужных страниц через индекс, потом читает страницы по порядку. — Зачем? — Когда строк много для Index Scan, но мало для Seq Scan. Лучший I/O паттерн. — Три метода: Seq Scan, Index Scan, Bitmap Index Scan. Оптимизатор выбирает.