0Pricing
SQL Interview Prep · 课时

BETWEEN、IN 与包含边界

掌握边界极端情况,以及 BETWEEN 如何处理端点

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

为什么边界问题会让候选人丢分

范围和集合筛选条件看起来很简单,因此面试官会利用边界情况设下陷阱。BETWEEN 包含两个端点,IN 隐藏着一个微妙的 NULL 陷阱,而日期范围最容易出现差一错误,悄悄导致报告中的数据失真。

本课将准确讲解 BETWEEN 如何处理端点、什么时候 IN 比串联的 OR 更简洁,以及专业人士处理日期时使用的半开区间模式。

BETWEEN 两端都包含

col BETWEEN a AND b 是 col >= a AND col <= b 的简写。两个端点都包含在内。

因此,price BETWEEN 10 AND 20 不仅会返回价格恰好为 10 或 20 的行,也会返回两者之间的所有行。面试中最常见的错误答案,是声称上界不包含在内。

SELECT *
FROM products
WHERE price BETWEEN 10 AND 20;
-- equivalent to: price >= 10 AND price <= 20

参数顺序很重要

BETWEEN 要求先写较小的值。col BETWEEN 20 AND 10 会展开为 col >= 20 AND col <= 10,这不可能为真,因此它会返回零行,而不是报错。

这是一个很常见的陷阱:查询正常执行,却什么也不返回,于是候选人误以为数据为空。请始终把较小的边界放在前面。

SELECT *
FROM products
WHERE price BETWEEN 20 AND 10;
-- returns NOTHING, not an error

日期范围中的差一错误

当要求查询一月份的全部数据时,许多候选人会写成 order_date BETWEEN '2024-01-01' AND '2024-01-31'。如果 order_date 是时间戳,这会排除 31 日午夜之后的所有数据,因为 2024-01-31 表示 2024-01-31 00:00:00。

1 月 31 日下午 2 点的订单会被排除。对于纯 DATE 列,这样写是有效的,但您不能想当然地假设列的类型。

SELECT *
FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31';
-- silently excludes Jan 31 afternoon if order_date is a timestamp

半开区间修正方案

处理日期时,专业的模式是使用半开区间:起始时间大于等于起点,结束时间严格小于下一个时间段。对于 DATE 和 TIMESTAMP 都是正确的,而且不需要了解列的时间精度。

请注意,上界是二月的第一天,而不是一月的最后一天。这样可以涵盖一月份的每一个时间点。

SELECT *
FROM orders
WHERE order_date >= '2024-01-01'
  AND order_date <  '2024-02-01';

NOT BETWEEN

col NOT BETWEEN a AND b 会展开为 col < a OR col > b。它会排除两个端点以及它们之间的所有值。

请注意:如果 col 是 NULL,NOT BETWEEN 的计算结果会是 UNKNOWN,因此 NULL 行会像使用普通 BETWEEN 时一样被排除。无论哪个方向,NULL 都不会满足范围测试。

SELECT *
FROM products
WHERE price NOT BETWEEN 10 AND 20;
-- price < 10 OR price > 20

IN:集合成员关系

col IN (a, b, c) 是 col = a OR col = b OR col = c 的简写。这是测试一个小型固定集合中是否包含某个值的简洁方式。

它比一长串 OR 更易读,而且由于整个集合测试是一个谓词,完全避免了优先级和括号的问题。

SELECT *
FROM orders
WHERE status IN ('pending', 'shipped', 'delivered');

NOT IN 与 NULL 陷阱

这是最令人畏惧的 IN 问题。如果 NOT IN 背后的列表或子查询包含一个 NULL,整个谓词就可能计算为 UNKNOWN,并返回零行。

原因是:x NOT IN (1, NULL) 会变成 x <> 1 AND x <> NULL,而 x <> NULL 永远不为真,而是 UNKNOWN。整个 AND 永远不可能为真。

SELECT *
FROM employees
WHERE manager_id NOT IN (SELECT id FROM managers);
-- returns NOTHING if any managers.id is NULL

修正 NOT IN

修复 NOT IN 的 NULL 陷阱有两种可靠方式:

  • 使用 WHERE id IS NOT NULL 从子查询中过滤掉 NULL
  • 更好的方式是将其重写为 NOT EXISTS,它在设计上能够正确处理 NULL

面试官认为 NOT EXISTS 是资深开发者的回答,因为它完全避开了这个陷阱,而且通常也能生成更好的执行计划。

SELECT e.*
FROM employees e
WHERE NOT EXISTS (
  SELECT 1 FROM managers m WHERE m.id = e.manager_id
);

IN 与子查询

IN 接受一个返回单列的子查询。WHERE customer_id IN (SELECT customer_id FROM vip) 会保留客户属于 VIP 集合的行。

普通的 IN(不是 NOT IN)能够安全处理子查询中的 NULL:列表中的 NULL 只会无法匹配,但不会影响那些确实匹配的行。这个陷阱只针对 NOT IN。

SELECT *
FROM orders
WHERE customer_id IN (SELECT customer_id FROM vip_customers);

使用行构造器进行多列 IN

一个常见的后续问题是:如何同时匹配多个列?使用行构造器将元组传递给 IN——它会按位置比较各列,比串联 OR (a = .. AND b = ..) 简洁得多。

  • 可读性好,也适合扩展到很长的允许列表。
  • 每个元组都必须按相同顺序列出各列。
SELECT *
FROM orders
WHERE (customer_id, status) IN ((101, 'paid'), (102, 'shipped'));

快速检查

回想一下 BETWEEN 如何处理其端点。

回顾

要点:

  • BETWEEN a AND b 包含两个端点;下界必须放在前面,否则会得到零行
  • 对于时间戳范围,请使用半开区间:>= start AND < next_period
  • IN 用于简洁地测试集合成员关系,并且能够安全处理 NULL
  • 只要列表中存在任何 NULL,NOT IN 就不会返回任何内容;请将其重写为 NOT EXISTS

反复出现的主题是:筛选条件可以完美执行,却仍然悄悄返回错误的行。

常见问题解答

「BETWEEN、IN 与包含边界」课时是免费的吗?

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

「BETWEEN、IN 与包含边界」这节课中我会学到什么?

掌握边界极端情况,以及 BETWEEN 如何处理端点 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 SQL Interview Prep 需要有经验吗?

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

「BETWEEN、IN 与包含边界」课时需要多长时间?

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

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

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

此课程中的所有课时

  1. AND/OR 优先级与括号
  2. BETWEEN、IN 与包含边界
  3. LIKE、通配符与转义
  4. 按计算值筛选
← 返回 SQL Interview Prep