0Pricing
SQL Academy · 课时

使用 IN 和 NOT IN 处理集合

使用 IN 和 NOT IN 根据值列表进行过滤,了解 NOT IN 中 NULL 带来的陷阱,并转换为 EXISTS 以获得安全语义。

使用 IN 和 NOT IN 处理集合 是 CoddyKit 上的免费 SQL Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Academy 课程共包含 4 节课。

IN:与列表匹配

IN 是多个 OR 条件的简写:

SELECT * FROM users WHERE country IN ('US', 'CA', 'GB');

-- Equivalent to:
SELECT * FROM users
WHERE country = 'US' OR country = 'CA' OR country = 'GB';

带子查询的 IN

您可以在右侧使用子查询:

SELECT * FROM orders
WHERE user_id IN (
  SELECT id FROM users WHERE country = 'US'
);

NOT IN:排除列表

过滤掉匹配的行:

SELECT * FROM users WHERE status NOT IN ('banned', 'deleted');

NOT IN 的 NULL 陷阱

如果右侧包含 NULL,NOT IN 会返回 NULL,而谓词为 NULL 的行会被丢弃。结果是零行。

-- Suppose blocked_names contains NULL:
SELECT name FROM users
WHERE name NOT IN (SELECT excluded_name FROM blocked_names);
-- → 0 rows, silently

-- Safer: filter out NULLs explicitly, or use NOT EXISTS:
SELECT name FROM users u
WHERE NOT EXISTS (
  SELECT 1 FROM blocked_names b WHERE b.excluded_name = u.name
);

为什么 NOT EXISTS 更安全

NOT EXISTS 使用标准的相关子查询语义,并且能够安全处理 NULL。大多数规划器会将其优化为与格式正确的 NOT IN 完全相同的方式。

IN 与 OR:可读性

相比冗长的 OR 链,IN 更清晰,而且规划器通常会以相同方式进行优化:

-- Hard to read:
WHERE country = 'US' OR country = 'CA' OR country = 'GB' OR ...

-- Clear:
WHERE country IN ('US', 'CA', 'GB', ...)

带元组的 IN(行构造器)

匹配多列组成的列对:

SELECT * FROM order_items
WHERE (order_id, product_id) IN (
  (1, 42), (2, 99), (3, 17)
);

索引使用

针对已建立索引的列使用 IN 列表时,可以执行多次索引查找(位图索引扫描)。通常速度很快。

-- Plan: Bitmap Index Scan + Bitmap Heap Scan
SELECT * FROM products WHERE id IN (1, 5, 99, 121, 4421);

很大的 IN 列表

包含数千个值的列表可能会变慢。建议使用:

  • 与实际表或临时表进行 JOIN
  • 使用 = ANY(array) 传递数组参数
SELECT * FROM products WHERE id = ANY(ARRAY[1,2,3,...]);

空 IN 列表

标准 SQL 不允许空的 IN 列表。一些客户端会传递占位值;更安全的做法是有条件地生成 SQL 条件。

-- Use empty array trick in PostgreSQL:
SELECT * FROM products WHERE id = ANY($1::bigint[]);
-- Pass {} to get zero matches without rewriting the SQL.

IN 与 JOIN

有时,使用 JOIN 比使用 IN 子查询更清晰:

-- With IN:
SELECT * FROM orders
WHERE user_id IN (SELECT id FROM users WHERE pro);

-- With JOIN:
SELECT o.*
FROM orders o
JOIN users  u ON u.id = o.user_id
WHERE u.pro;

回顾

IN 是表示集合成员关系的简便形式。

  • 为了可读性,优先使用 IN 而不是 OR
  • NOT IN 遇到 NULL 时很危险,优先使用 NOT EXISTS
  • 对于大型集合,使用 JOIN 或传递数组

快速检查

当子查询可能包含 NULL 时,NOT IN (subquery) 最安全的替代方式是什么?

常见问题解答

「使用 IN 和 NOT IN 处理集合」课时是免费的吗?

是的 — 「使用 IN 和 NOT IN 处理集合」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Academy 课程的其余内容,请升级到 CoddyKit PRO。 SQL Academy 课程共包含 4 节课。

「使用 IN 和 NOT IN 处理集合」这节课中我会学到什么?

使用 IN 和 NOT IN 根据值列表进行过滤,了解 NOT IN 中 NULL 带来的陷阱,并转换为 EXISTS 以获得安全语义。 你通过在浏览器中直接运行的动手代码来练习 SQL Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 SQL Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 SQL Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「使用 IN 和 NOT IN 处理集合」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 SQL Academy 课中编写并运行代码吗?

能。每节 SQL Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. LIKE 模式与通配符
  2. 使用 IN 和 NOT IN 处理集合
  3. 使用 BETWEEN 处理范围
  4. IS NULL、IS NOT NULL 与 COALESCE
← 返回 SQL Academy