Как выбрать строки по списку значений в SQL (оператор IN)?
Нужно выбрать заказы со статусом «новый», «оплачен» или «отправлен». Писать три условия через OR долго. Есть ли способ выбрать по списку значений одним условием? Как работает оператор IN?
2 ответа
Да, для проверки «значение входит в список» есть оператор IN:
SELECT *
FROM orders
WHERE status IN ('new', 'paid', 'shipped');
Это полный эквивалент длинной записи:
WHERE status = 'new' OR status = 'paid' OR status = 'shipped'
только короче и читается лучше.
Есть и обратный вариант — NOT IN, чтобы исключить значения:
SELECT * FROM orders
WHERE status NOT IN ('cancelled', 'refunded');
Очень мощно, что в скобках может быть не только список, но и подзапрос:
SELECT name FROM customers
WHERE id IN (SELECT customer_id FROM orders WHERE total > 5000);
Здесь сначала выполнится внутренний запрос (id клиентов с крупными заказами), а внешний выберет их имена.
Осторожно с NOT IN и NULL! Если подзапрос или список содержит NULL, NOT IN может неожиданно вернуть ноль строк. Это известная ловушка: сравнение с NULL даёт «неизвестно», и вся проверка ломается. В таких случаях надёжнее использовать NOT EXISTS или добавить WHERE customer_id IS NOT NULL в подзапрос.
Маленький лайфхак: если список значений очень длинный (тысячи штук), огромный IN (...) может тормозить и упираться в лимиты СУБД. В таких случаях значения кладут во временную таблицу и делают JOIN или подзапрос по ней. Но для десятка значений IN — самый удобный и читаемый вариант, не усложняйте.