EXISTS / IN / NOT EXISTS (подзапрос)
Oracle
-- Customers with orders (EXISTS)
SELECT name FROM customer m
WHERE EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);
-- List membership with IN
SELECT name FROM customer
WHERE city IN ('Ankara', 'Izmir');
-- Customers with no orders at all (NOT EXISTS)
SELECT name FROM customer m
WHERE NOT EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);EXISTS проверяет, возвращает ли коррелированный подзапрос хотя бы одну строку (останавливается на первом совпадении, поэтому быстр). IN проверяет, входит ли значение в список/результат подзапроса. Осторожно: если подзапрос может вернуть NULL, NOT IN даёт неожиданные результаты; NOT EXISTS надёжнее. Оптимизатор Oracle часто превращает оба в один и тот же план.
PostgreSQL
SELECT name FROM customer m
WHERE EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);
SELECT name FROM customer
WHERE city IN (SELECT city FROM target_cities);
SELECT name FROM customer m
WHERE NOT EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);PostgreSQL полностью поддерживает EXISTS/IN/NOT EXISTS. С NOT IN, если подзапрос содержит NULL, весь результат может оказаться пустым, поэтому рекомендуются NOT EXISTS или LEFT JOIN ... IS NULL. Планировщик в большинстве случаев обрабатывает IN и EXISTS одинаково, как semi-join.
MySQL
SELECT name FROM customer m
WHERE EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);
SELECT name FROM customer
WHERE city IN ('Ankara', 'Izmir');
SELECT name FROM customer m
WHERE NOT EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);MySQL/MariaDB поддерживают EXISTS/IN/NOT EXISTS. До MySQL 5.6 коррелированные подзапросы могли быть медленными; 5.6+ ускорил подзапросы IN оптимизациями semi-join и материализации. Ловушка NOT IN + NULL действует и здесь.
SQL Server
SELECT name FROM customer m
WHERE EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);
SELECT name FROM customer
WHERE city IN (SELECT city FROM target_cities);
SELECT name FROM customer m
WHERE NOT EXISTS (SELECT 1 FROM orders s WHERE s.customer_id = m.id);SQL Server поддерживает EXISTS/IN/NOT EXISTS, и оптимизатор в основном обрабатывает их как semi/anti-join. Если подзапрос NOT IN содержит NULL, результат может неожиданно оказаться пустым; NOT EXISTS — безопасный выбор. Для похожей логики принадлежности можно использовать и INTERSECT/EXCEPT.
MongoDB
// IN equivalent: the $in operator
db.customer.find({ city: { $in: ["Ankara", "Izmir"] } })
// EXISTS equivalent: match check with $lookup + $match
db.customer.aggregate([
{ $lookup: { from: "orders", localField: "id",
foreignField: "customer_id", as: "s" } },
{ $match: { "s.0": { $exists: true } } } // at least one order
])В MongoDB принадлежность списку значений проверяется операторами $in / $nin. Эквивалент EXISTS с подзапросом — получить массив совпадающих документов через $lookup и фильтровать по тому, пуст ли массив. Проверка наличия поля — отдельный оператор { field: { $exists: true } } (наличие поля, а не связь строк).
Redis
# Membership check with Set/Hash:
SISMEMBER target_cities "Ankara" # is it in the set? (IN-like)
EXISTS customer:1 # does the key exist?В Redis нет подзапросов. Для проверки принадлежности значения используйте SISMEMBER на Set (аналог IN). Команда EXISTS — не подзапрос; она возвращает, существует ли заданный ключ. Реляционные проверки существования выполняются на стороне приложения чтением нескольких ключей.
Elasticsearch
# IN equivalent: terms query
GET customer/_search
{ "query": { "terms": { "city": ["Ankara", "Izmir"] } } }
# Field existence: exists query
GET customer/_search
{ "query": { "exists": { "field": "phone" } } }В Elasticsearch эквивалент IN — запрос 'terms' (совпадение с одним из нескольких значений), а NOT IN — terms внутри bool must_not. Запрос 'exists' не соответствует SQL EXISTS; он проверяет, есть ли у поля значение в документе. Коррелированный EXISTS между таблицами обычно требует денормализации.