🎯 本月只剩几天支持 SQLTest.online,帮助我们让 SQL 练习对每个人都免费。 今天捐赠 →
SQL 代码已复制到剪贴板

在 WHERE 中组合多个条件

第 2.3 课 · 阅读时间:约 7 分钟 · 练习题 ↓

本课介绍如何在 WHERE 子句中使用逻辑运算符 AND、OR 和 NOT 组合多个条件。你将学会把多个表达式连接起来,构建更精细的过滤条件,准确取出需要的数据子集。我们还会讲解运算符优先级,以及为什么要用括号控制求值顺序、保证查询结果正确。

在 SQL 中组合多个筛选条件

在上一课中,我们学习了如何在 WHERE 子句中使用简单的比较运算符。然而,实际的数据分析经常需要同时按多个条件过滤。为此我们使用逻辑运算符:AND、OR 和 NOT。

SQL 逻辑运算符 AND、OR 和 NOT:AND 先于 OR 计算,因此 (rating = 'G' OR rating = 'PG') AND length < 60 返回 43 部电影,而不加括号的同一条件返回 200 部

SQL 中的逻辑运算符

逻辑运算符可以把 WHERE 子句中的多个表达式连接起来,构建更复杂的过滤条件。

AND 运算符

只有当 AND 连接的所有条件都为真时,AND 运算符才返回该行。它用于缩小结果范围。

示例(Sakila 数据库) 假设我们要找出分级为 'G' 并且时长少于 80 分钟的电影:

SELECT title, length, rating
FROM film
WHERE length < 80 AND rating = 'G';

结果:只返回同时满足两个条件的电影。

OR 运算符

只要 OR 连接的条件中任意一个为真,OR 运算符就返回该行。它用于扩大结果范围。

示例(Sakila 数据库) 查找名字为 'NICK' 或 'ED' 的演员:

SELECT first_name, last_name
FROM actor
WHERE first_name = 'NICK' OR first_name = 'ED';

结果:演员名字与其中至少一个值匹配的行。

NOT 运算符

当条件不为真时,NOT 运算符返回该行。在实践中,它常与 IN 和 LIKE 一起使用,用来排除一组值或某种文本模式。

示例 1:排除一个分级

查找除 'R' 级以外的所有电影:

SELECT title, rating
FROM film
WHERE NOT rating = 'R';

结果:分级不是 'R' 的所有电影。

示例 2:用 NOT IN 排除多个值

如果要一次排除多个分级,用 NOT IN 更方便:

SELECT title, rating
FROM film
WHERE rating NOT IN ('R', 'NC-17');

结果:分级不在 'R' 和 'NC-17' 列表中的电影。

示例 3:用 NOT LIKE 对模式取反

如果要排除以字母 A 开头的片名:

SELECT title
FROM film
WHERE title NOT LIKE 'A%';

结果:片名不以 A 开头的电影。

XOR 运算符(异或,很少使用)

只有当两个条件中恰好一个为真时,XOR 运算符才返回真。实践中它很少使用,因为并非所有 SQL 方言都支持它,而且会降低查询的可读性。

示例(Sakila 数据库) 查找只满足一个条件的电影:要么时长少于 60 分钟,要么分级为 'G',但两者不能同时满足:

SELECT title, length, rating
FROM film
WHERE length < 60 XOR rating = 'G';

为了在不同数据库之间通用,同样的逻辑通常用 AND/OR/NOT 来写。


运算符优先级

当你在一条查询中组合多个运算符(例如同时使用 AND 和 OR)时,SQL 会按照特定的运算顺序(优先级)求值。

  1. 首先计算 NOT。
  2. 其次计算 AND。
  3. XOR(如果你的 SQL 方言支持)通常在 AND 之后计算。
  4. 最后计算 OR。

括号的作用: 和数学中一样,应该使用括号 () 来控制求值顺序,并让查询更易读。如果不加括号,SQL 会默默套用默认的优先级,结果可能并不是你想要的。


查找时长少于 60 分钟的 'G' 和 'PG' 级电影

有错误的查询:缺少括号

-- BUG: AND binds tighter than OR, so this is evaluated as:
-- rating = 'G'  OR  (rating = 'PG' AND length < 60)
-- Result: ALL 'G' films (any length) + only SHORT 'PG' films
SELECT title, length, rating
FROM film
WHERE rating = 'G' OR rating = 'PG' AND length < 60;

错在哪里: AND 条件先被计算,所以 length < 60 过滤只作用于 'PG' 级电影,而所有 'G' 级电影无论时长多少都会被返回。

修正后的查询:用括号明确意图

-- CORRECT: parentheses force OR to be evaluated first
-- Result: only films rated 'G' OR 'PG' AND shorter than 60 minutes
SELECT title, length, rating
FROM film
WHERE (rating = 'G' OR rating = 'PG') AND length < 60;

结果:只返回分级为 'G' 或 'PG' 且时长少于 60 分钟的电影。


同时排除 'R' 级和 'NC-17' 级电影

有错误的查询:NOT 只否定第一个条件

-- BUG: NOT applies only to the immediately following condition
-- Equivalent to: (NOT rating = 'R') AND rating = 'NC-17'
-- Result: films rated 'NC-17' that are also not rated 'R' - always empty
SELECT title, rating, length
FROM film
WHERE NOT rating = 'R' AND rating = 'NC-17';

错在哪里: NOT 只否定了 rating = 'R',而 rating = 'NC-17' 仍然是一个正向过滤条件。实际上,这条查询会返回所有 'NC-17' 级电影:因为 'NC-17' 不是 'R',这些行总是满足 NOT 条件。查询非但没有排除 NC-17 级电影,返回的恰恰是你想排除的那些电影。

方案 A:写两个明确的 NOT 条件

-- CORRECT: each condition is independently negated
SELECT title, rating, length
FROM film
WHERE NOT rating = 'R' AND NOT rating = 'NC-17';

方案 B:NOT 加括号(更简洁)

-- CORRECT: NOT applies to the whole OR group
SELECT title, rating, length
FROM film
WHERE NOT (rating = 'R' OR rating = 'NC-17');

两种方案返回的结果相同。排除多个值时通常更推荐方案 B,因为列表变长时它更容易扩展。


常见问题

什么时候用 AND,什么时候用 OR?

当一行必须同时满足所有条件时,使用 AND。当满足多个条件中的任意一个就够时,使用 OR。如果两个运算符出现在同一条查询中,最好加上括号。

NOT IN 与多个 AND 条件有什么不同?

NOT IN 是从同一列中排除多个值的简洁写法。与一长串用 AND 连接的否定比较相比,它更易读,也更容易扩展。

什么时候使用 NOT LIKE?

当你想排除与某个文本模式匹配的行时,使用 NOT LIKE。它适合按前缀、后缀或子串做反向过滤。


面试问题

面试时你会如何解释 SQL 的运算符优先级?

在 SQL 中,先计算 NOT,再计算 AND,最后计算 OR。当查询混用多个运算符时,括号可以明确表达预期的逻辑,防止出现意外结果。

什么时候用 NOT IN 而不是 NOT =?

当需要从同一列中排除多个值时,使用 NOT IN。与用 AND 重复写多个比较相比,它更易读,也更容易扩展。

NOT LIKE 如何工作?

NOT LIKE 返回与指定模式不匹配的行。例如,title NOT LIKE 'A%' 会排除所有以 A 开头的片名。

为什么括号在复杂的 WHERE 子句中很重要?

括号控制求值顺序,消除 AND 和 OR 之间的歧义。它们让你准确写出想要的逻辑,而不是依赖默认的优先级。

本课要点:

  • 用 AND 确保所有条件都满足。
  • 用 OR 查找满足多个条件中任意一个的行。
  • 用 NOT、NOT IN 和 NOT LIKE 排除数据。
  • 谨慎使用 XOR:它可能有用,但并非所有 SQL 方言都支持。
  • 混用 AND 和 OR 时一定要加括号 (),以避免逻辑错误并提高清晰度。

尝试解决以下任务,以巩固您在本课中学到的内容。

  1. 姓氏以 "A" 开头的客户
  2. 查找以字母 "A" 开头的客户 (2)
  3. 逻辑运算符的执行顺序
  4. 受限影片列表
  5. 受限电影列表