SQL WHERE 详解:10 分钟内像专家一样过滤数据
用一个贴近生活的场景吸引读者:假设你有一个包含 1 千万条客户记录的数据库,但你只需要找到上个月购物金额超过 100 美元的纽约客户。如果没有 WHERE 子句,你就会被淹没在不相关的数据中。
WHERE 子句就是你的过滤器--从海量数据集中准确提取所需内容的精确工具。
在本 10 分钟指南中,你将掌握
- 使用比较运算符进行基本过滤
- 使用 AND、OR、NOT 组合条件
- 使用 LIKE 进行模式匹配
- 正确处理 NULL 值(初学者的头号错误)
- 常见的 WHERE 子句陷阱以及如何避免这些陷阱
最后,您将自信地编写 WHERE 子句,并避免 90% 的 SQL 初学者都会犯的错误。
让我们深入学习。
什么是 WHERE 子句?
WHERE 子句根据指定条件过滤记录。将其视为质量控制检查点:只有符合条件的记录才能通过。
基本语法:
sql
SELECT column1, column2
FROM table_name
WHERE condition;
**关键概念:**WHERE 会对每一行进行单独评估。如果条件为 "真",则结果中包含该行。如果条件为 FALSE 或 NULL,则将其排除在外。
执行顺序很重要:
- FROM - 识别表
- WHERE - 筛选记录
- SELECT - 选择列
这个顺序就是为什么不能在 WHERE 中引用列别名的原因(稍后将详细介绍)。
1.比较操作符:基本工具包
六个基本操作
每个 WHERE 子句都从这里开始:
等于 (=)
sql
SELECT * FROM employees
WHERE department = 'Sales';
查找完全匹配。记住:文本使用单引号,数字不使用引号。
不等于 (<> 或 !=)
sql
SELECT * FROM orders
WHERE status <> 'cancelled';
指定值以外的所有内容。
大于 (>) 和小于 (<)
sql
SELECT * FROM products
WHERE price > 100;
SELECT * FROM students
WHERE age < 18;
大于/小于或等于 (>= 和 <=)
sql
SELECT * FROM employees
WHERE salary >= 50000 AND salary <= 100000;
实用提示
**字符串:**始终使用单引号"文本"
,而不是双引号
✅数字: 在年龄 = 25 的情况下,
不需要引号
✅**日期:**使用 ISO 格式WHERE hire_date >= "2025-01-01
❌常见错误: WHERE 类别 = 电子
(缺少引号)
✅正确: WHERE 类别 = "电子产品
2.逻辑操作符:AND, OR, NOT
像专家一样组合条件
AND 运算符- 所有条件必须为真:
sql
SELECT * FROM employees
WHERE department = 'Sales'
AND salary > 50000
AND hire_date >= '2020-01-01';
将 AND 运算符视为缩小结果范围:您是在堆叠要求。
OR 运算符- 至少一个条件必须为真:
sql
SELECT * FROM employees
WHERE department = 'Sales'
OR department = 'Marketing'
OR department = 'HR';
OR 运算符扩大了结果范围:你接受了多种可能性。
NOT 运算符- 否定一个条件:
sql
SELECT * FROM employees
WHERE NOT department = 'Sales';
-- Returns everyone except Sales
第一大陷阱:混合 AND/OR 而不加括号
❌ 这并不像预期的那样有效:
sql
SELECT * FROM products
WHERE category = 'Electronics'
OR category = 'Computers'
AND price < 500;
**为什么?**AND 的优先级高于 OR。SQL 将其解释为
"所有电子产品(任何价格) OR(500 美元以下的电脑)
因此,你会在 "500 美元以下 "的结果中看到价值 5000 美元的笔记本电脑!
✅ 始终使用括号:
sql
SELECT * FROM products
WHERE (category = 'Electronics' OR category = 'Computers')
AND price < 500;
**黄金法则:**如果混合 AND/OR,请使用括号。Every.每次。每一次。
3.使用 LIKE 进行模式匹配
灵活搜索的通配符
当您不知道准确值时,可使用带有通配符的 LIKE:
百分号 (%) - 匹配零个或多个字符
sql
-- Starts with 'John'
WHERE first_name LIKE 'John%'
-- Matches: John, Johnny, Johnson
-- Ends with 'son'
WHERE last_name LIKE '%son'
-- Matches: Johnson, Anderson, Wilson
-- Contains 'admin'
WHERE email LIKE '%admin%'
-- Matches: [admin@company.com](mailto:admin@company.com), [webadmin@site.org](mailto:webadmin@site.org)
下划线 (_) - 完全匹配一个字符
sql
-- Phone pattern: XXX-XXX-XXXX
WHERE phone LIKE '___-___-____'
-- 4-letter codes starting with A
WHERE product_code LIKE 'A___'
-- Matches: A001, ABCD, A999
NOT LIKE - 排除模式:
sql
WHERE email NOT LIKE '%@[gmail.com](http://gmail.com)'
-- Everyone except Gmail users
性能警告 ⚠️
以 % 开头的模式(LIKE '%search%'
)不能使用索引。它们在大型表中运行速度较慢。请谨慎使用。
快速: LIKE 'John%'
(可以使用索引)
慢: LIKE '%John%'
(全表扫描)
4.NULL 陷阱:为什么= NULL
从不可行
最常见的 WHERE 子句错误
❌ 这是错误的,会困扰你:
sql
SELECT * FROM employees
WHERE manager_id = NULL;
-- Returns 0 rows, even if NULLs exist!
✅ 始终使用 IS NULL:
sql
SELECT * FROM employees
WHERE manager_id IS NULL;
-- Correctly finds rows with NULL manager_id
为什么重要
NULL 的意思是 "未知",而不是 "空"。在 SQL 的逻辑中
NULL = NULL
返回NULL
(不是 TRUE!)。NULL <> NULL 返回 NULL
(而不是 FALSE!)。- 任何与 NULL 的比较都返回 NULL
NULL 就像一个黑洞:它吞噬比较结果,却什么也不返回。
IS NULL- 检验 NULL 值:
sql
WHERE phone IS NULL
-- Customers without phone numbers
IS NOT NULL- 检验非空值:
sql
WHERE email IS NOT NULL
-- Users who have emails
计算中的 NULL
NULL 会 "感染 "任何计算:
sql
-- If discount is NULL:
price - discount = NULL (not the original price!)
解决方案:使用 COALESCE 处理 NULL:
sql
SELECT
product_name,
price,
price - COALESCE(discount, 0) AS sale_price
FROM products;
-- COALESCE(discount, 0) means: use discount if it exists, otherwise 0
记住NULL = 未知,不为零,不为空。特别处理。
5.高级 WHERE 技术
范围查询的 BETWEEN
而不是这样:
sql
WHERE price >= 100 AND price <= 500
使用 BETWEEN:
sql
WHERE price BETWEEN 100 AND 500
-- Includes both 100 and 500 (inclusive)
也适用于日期:
sql
WHERE order_date BETWEEN '2025-01-01' AND '2025-12-31'
多个值的 IN
而不是这样:
sql
WHERE status = 'pending'
OR status = 'processing'
OR status = 'shipped'
使用 IN:
sql
WHERE status IN ('pending', 'processing', 'shipped')
-- Much cleaner!
NOT IN:
sql
WHERE department NOT IN ('Sales', 'Marketing')
-- Everyone except these departments
EXISTS 用于子查询检查
检查相关数据是否存在:
sql
SELECT * FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.customer_id
)
-- Customers who have placed at least one order
6.常见 WHERE 子查询错误
错误 1:使用列别名
❌ 不会起作用:
sql
SELECT
price * 1.1 AS price_with_tax
FROM products
WHERE price_with_tax > 100;
-- Error: 'price_with_tax' doesn't exist
**为什么?**WHERE 在 SELECT 之前运行。别名还不存在。
✅ 重复计算:
sql
WHERE price * 1.1 > 100
错误 2:忘记引号
❌ WHERE 类别 = 电子产品
✅ WHERE 类别 = "电子产品
错误 3:大小写敏感性
不同的数据库对此有不同的处理方法。请注意!
sql
-- May or may not match 'SMITH'
WHERE last_name = 'Smith'
-- Force case-insensitive:
WHERE LOWER(last_name) = 'smith'
7.WHERE 与 HAVING:区别是什么?
WHERE在分组前过滤单行:
sql
SELECT department, COUNT(*)
FROM employees
WHERE salary > 50000 -- Filter rows first
GROUP BY department;
HAVING在聚合后过滤分组:
sql
SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING COUNT(*) > 10; -- Filter groups
经验法则:
- 对列值使用 WHERE
- 对聚合结果(COUNT、SUM、AVG)使用 HAVING
实践练习:测试技能
尝试为这些情况编写 WHERE 子句:
- 查找价格在 50 美元到 200 美元之间的产品
- 查找加利福尼亚州或纽约州的客户
- 查找 2020 年后聘用且薪资高于 60,000 美元的员工
- 查找名称中包含 "Pro "的产品
- 查找没有跟踪号码(NULL)的订单
- 查找技术部或市场部的活跃用户(状态 ="活跃")。
答案
sql
-- 1
WHERE price BETWEEN 50 AND 200
-- 2
WHERE state IN ('CA', 'NY')
-- 3
WHERE hire_date > '2020-12-31' AND salary > 60000
-- 4
WHERE product_name LIKE '%Pro%'
-- 5
WHERE tracking_number IS NULL
-- 6
WHERE status = 'active'
AND (department = 'Tech' OR department = 'Marketing')
结论:您的 WHERE 子句核对表
现在,您已经拥有了像专家一样过滤数据的工具。在编写下一个 WHERE 子句之前,请记住
✅ 黄金法则:
- 对字符串使用单引号:
"文本
- 使用 IS NULL,切勿使用 = NULL
- 混合 AND/OR?始终添加括号
- LIKE '%模式%'很慢--小心使用
- WHERE 在 SELECT 之前运行--不能使用别名
日常常用模式:
WHERE 列 = '值'
- 完全匹配WHERE 列 IN ('a', 'b', 'c')
- 多个值WHERE 列介于 x 和 y 之间
--范围WHERE 列 LIKE 'pattern%'
- 部分匹配WHERE column IS NULL
- 查找缺失数据
下一步
- 练习 20 多种不同的 WHERE 条件
- 学习使用 JOIN 跨多个表进行筛选
- 掌握用于复杂过滤的子查询
现在去过滤一些数据吧!🚀