当 WHERE 子句同时出现 AND 和 OR 时,查询按自己的分组规则执行,而不是按中文句子听起来的意思。 在标准 SQL 中,AND 先于 OR 计算。用括号可以自己决定分组。
带筛选条件的查询属于数据库与查询推理。写一个简单的 SELECT 筛选和用正确的布尔分组组合条件这两课会一步步建立这项技能。
为什么会出现错误的分组?
我们说“2015 年后出版的科幻或奇幻书”,脑子里自动分成(科幻或奇幻)并且 2015 年后。SQL 不读中文。它看到用 OR 和 AND 连起来的三个条件,就按优先级计算:先 AND,后 OR。
这意味着同样的一句话可能是两个不同的查询。只有括号才能确定含义。
例题
名为 Books 的表有五行。
| id | title | genre | year |
|---|---|---|---|
| 1 | Dune | SciFi | 1965 |
| 2 | Nova | Fantasy | 2019 |
| 3 | Orbit | SciFi | 2021 |
| 4 | Ember | Fantasy | 2010 |
| 5 | Drift | Mystery | 2022 |
目标: 列出 2015 年后出版的 SciFi 或 Fantasy 书的书名。
尝试 A,没有括号:
SELECT title
FROM Books
WHERE genre = 'SciFi' OR genre = 'Fantasy' AND year > 2015;
第一步。 AND 先结合,所以查询被理解为:genre = ‘SciFi’ OR(genre = ‘Fantasy’ AND year > 2015)。
第二步。 每一行 SciFi 都符合,不管年份:Dune(1965)和 Orbit(2021)。
第三步。 Fantasy 行只有年份在 2015 年后才符合:Nova(2019)符合,Ember(2010)不符合。
A 的结果: Dune、Nova、Orbit。共三行,而 Dune 并不是 2015 年后出版的。
尝试 B,加括号:
SELECT title
FROM Books
WHERE (genre = 'SciFi' OR genre = 'Fantasy') AND year > 2015;
第一步。 先算括号:第 1 到 4 行是 SciFi 或 Fantasy(Drift 是 Mystery,被排除)。
第二步。 再对这些行应用 year > 2015:Nova(2019)和 Orbit(2021)留下,Dune(1965)和 Ember(2010)被淘汰。
B 的结果: Nova、Orbit。两行,正是目标要求的。
要避免的错误
错误一:没加括号。 如尝试 A,查询能运行,却在回答另一个问题。因为查询本身合法,所以没有任何警告。
错误二:中文说“或”的地方写成了 AND。 genre = 'SciFi' AND genre = 'Fantasy' 要求一个字段同时是两种类型。没有一行能做到,所以返回零行。
更正: 先把条件用话说出来,决定分组,再写括号。如果你想表达“其中任意一个”,就在括号里用 OR。
每次都能发现问题的流程
- 把问题写成一句话,并给各组划线。
- 写查询时,在每一组外面加括号。
- 取五行样本,手动标出符合的行。
- 运行或跟踪查询,与你的标记对比。
伪代码跟踪训练器和 Python 推理沙盒在小算法上练习的,正是这种手动跟踪的习惯。
自测
使用上面的 Books 表。
1. SELECT title FROM Books WHERE genre = 'Mystery' OR year < 2000; 返回什么?
Show answer
Drift(Mystery)和 Dune(1965,早于 2000)。两个条件用 OR 连接,所以一行只需满足其一。结果是 Dune 和 Drift。2. 写一个查询:2000 年后的 SciFi 书,并且 id 大于 1。
Show answer
`SELECT title FROM Books WHERE genre = 'SciFi' AND year > 2000 AND id > 1;` 只有 Orbit 符合。三个条件都用 AND,所以不需要括号,但一行必须全部通过。3. 查询需要 Fantasy 书,或者 2020 年后的任何书。WHERE genre = 'Fantasy' OR year > 2020 返回哪些行?
Show answer
Nova 和 Ember(Fantasy),加上 Orbit(2021)和 Drift(2022)。Dune 既不是 Fantasy,也不晚于 2020。结果共四行。接下来
在解释查询为什么返回零行中练习分组,如果逻辑运算符本身还不牢,先复习计算带括号的逻辑表达式。
如果你会写 SQL,却总是对结果没把握,一对一线上计算机科学补习可以从你自己的查询出发,从 RM80 起的付费试听课开始。