课程 2.3 · 阅读时间: ~7 分钟
本 SQL 课程讲解如何使用逻辑运算符 AND、OR 和 NOT 在 WHERE 子句中组合多个条件。您将学习如何通过连接多个表达式来创建高级数据库过滤器,以检索特定数据子集。课程解释了运算符优先级以及使用括号控制评估顺序和确保查询准确性的重要性。掌握复杂的数据过滤技术,以增强您的 SQL 查询技能,以便进行更有效的数据分析和报告。
在 WHERE 中组合多个条件
在 SQL 中组合多个标准
在上一课中,我们学习了如何使用简单比较运算符的 WHERE 子句。然而,现实世界的数据分析通常需要同时按多个标准进行过滤。为此,我们使用逻辑运算符:AND、OR 和 NOT。
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 遵循特定的运算顺序(优先级)。
NOT首先被评估。AND其次被评估。XOR(如果您的 SQL 方言支持)通常在AND之后被评估。OR最后被评估。
括号的力量:
就像在数学中一样,您应该使用括号 () 来控制评估顺序,使您的查询更具可读性。如果没有它们,SQL 会默默地应用其默认优先级——结果可能不是您所期望的。
查找时长少于 60 分钟的 'G' 和 'PG' 电影
有问题的查询——缺少括号:
-- BUG: AND 的优先级高于 OR,因此这被评估为:
-- rating = 'G' OR (rating = 'PG' AND length < 60)
-- 结果:所有 'G' 电影(任何长度)+ 仅短的 'PG' 电影
SELECT title, length, rating
FROM film
WHERE rating = 'G' OR rating = 'PG' AND length < 60;
为什么错误: AND 条件首先被评估,因此 length < 60 过滤器仅适用于 'PG' 电影,而所有 'G' 电影——无论长度——都被忽略。
修正后的查询——括号使意图明确:
-- CORRECT: 括号强制 OR 先被评估
-- 结果:仅返回评分为 'G' 或 'PG' 且时长少于 60 分钟的电影
SELECT title, length, rating
FROM film
WHERE (rating = 'G' OR rating = 'PG') AND length < 60;
结果:仅返回评分为 'G' 或 'PG' 且时长少于 60 分钟的电影。
排除评分为 'R' 和 'NC-17' 的电影
有问题的查询——NOT 仅否定第一个条件:
-- BUG: NOT 仅适用于紧随其后的条件
-- 等同于: (NOT rating = 'R') AND rating = 'NC-17'
-- 结果:评分为 'NC-17' 的电影且不评分为 'R' — 始终为空
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 条件始终对这些行成立。查询返回了您想要排除的电影。
选项 A — 两个显式的 NOT 条件:
-- CORRECT: 每个条件独立否定
SELECT title, rating, length
FROM film
WHERE NOT rating = 'R' AND NOT rating = 'NC-17';
选项 B — 使用括号的 NOT(更简洁):
-- CORRECT: NOT 应用于整个 OR 组
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时,始终使用括号()以避免逻辑错误并提高清晰度。
在下一课中,我们将学习如何 排序和限制 结果,以更有效地组织您的数据。