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 等同地作为半连接处理。
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 子查询。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,优化器大多将其作为半连接/反连接处理。如果 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 没有子查询。值成员判断可对 Set 使用 SISMEMBER(类似 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 是放在 bool must_not 中的 terms。'exists' 查询并不对应 SQL EXISTS;它检查文档中某个字段是否有值。跨表的相关 EXISTS 通常需要反规范化。