Ответ вслух Middle Подзапросы и CTE спрашивают часто обновлено

EXISTS против IN

Вопрос

Чем EXISTS отличается от IN, а NOT EXISTS от NOT IN? Что выберешь и почему?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

IN проверяет, входит ли значение в список или результат подзапроса. EXISTS проверяет, вернул ли коррелированный подзапрос хоть одну строку.

Что должно прозвучать в ответе

  • 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 ошибок.