EXISTS против IN
Вопрос
Чем EXISTS отличается от IN, а NOT EXISTS от NOT IN? Что выберешь и почему?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
IN сравнивает значение со списком, EXISTS проверяет факт наличия строк в коррелированном подзапросе
Для положительной проверки результаты совпадают, PostgreSQL превращает оба в semi-join
NOT IN при NULL в подзапросе даёт пустой результат, NOT EXISTS работает корректно
Для «нет в другой таблице» выбираю NOT EXISTS или LEFT JOIN ... IS NULL
Миф «IN всегда медленнее» устарел, смотреть план
Что могут спросить следом
- Как PostgreSQL выполняет NOT EXISTS?
- Когда IN со списком литералов становится проблемой?
- Перепиши NOT EXISTS через LEFT JOIN.
Разбор
IN проверяет, входит ли значение в список или результат подзапроса. EXISTS проверяет, вернул ли коррелированный подзапрос хоть одну строку. Для положительной проверки они дают одинаковый результат, и PostgreSQL превращает оба в semi-join, так что совет «EXISTS всегда быстрее» сейчас не про производительность, а про привычку. Существенная разница в отрицании. NOT IN разворачивается в цепочку <> через AND, и если в подзапросе есть хоть один NULL, условие никогда не станет true, результат пустой. NOT EXISTS таких проблем не имеет и выполняется как anti-join. Поэтому для «у кого нет» я пишу NOT EXISTS или LEFT JOIN ... WHERE правая.id IS NULL, а спорные случаи проверяю через EXPLAIN.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Термины по теме
Ещё по теме «Подзапросы и CTE»
- Полный путь категории в дереве
- Клиенты, у которых все заказы оплачены
- Дни без продаж по регионам
- Цепочка руководителей вверх по дереву
- Дороже любой книги: ALL против MAX
- Категория с максимальной выручкой
- Два последних заказа каждого клиента через LATERAL
- Дороже среднего по своей категории