WHERE 条件
WHERE 子句用于过滤记录,只返回满足条件的行。本章将详细介绍 WHERE 的各种用法。
基本 WHERE
比较运算符
WHERE 支持以下比较运算符:
| 运算符 | 含义 | 示例 |
|---|---|---|
= | 等于 | age = 18 |
<> 或 != | 不等于 | age != 18 |
> | 大于 | age > 18 |
< | 小于 | age < 18 |
>= | 大于等于 | age >= 18 |
<= | 小于等于 | age <= 18 |
-- 查询年龄等于 18 的用户
SELECT * FROM users WHERE age = 18;
-- 查询年龄大于 18 的用户
SELECT * FROM users WHERE age > 18;
-- 查询城市不是北京的用户
SELECT * FROM users WHERE city != '北京';
字符串比较
字符串需要用单引号包裹:
-- 精确匹配
SELECT * FROM users WHERE name = '张三';
-- 字符串比较按字典顺序
SELECT * FROM products WHERE name < 'C';
日期比较
日期也需要用单引号包裹:
-- 查询特定日期
SELECT * FROM orders WHERE order_date = '2024-01-01';
-- 查询日期范围
SELECT * FROM orders WHERE order_date > '2024-01-01';
SELECT * FROM orders WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31';
逻辑运算符
AND 与运算
所有条件都为真时返回 true:
-- 查询年龄大于 18 且城市为北京的用户
SELECT * FROM users
WHERE age > 18 AND city = '北京';
-- 多个 AND 条件
SELECT * FROM products
WHERE category = '电子产品'
AND price > 1000
AND stock > 0;
OR 或运算
任一条件为真时返回 true:
-- 查询城市为北京或上海的用户
SELECT * FROM users
WHERE city = '北京' OR city = '上海';
-- 查询特定状态
SELECT * FROM orders
WHERE status = 'pending' OR status = 'processing';
NOT 非运算
取反条件:
-- 查询不是北京的用户
SELECT * FROM users WHERE NOT city = '北京';
-- 查询不等于特定值
SELECT * FROM products WHERE NOT category = '电子产品';
运算符优先级
AND 的优先级高于 OR:
-- 这条语句的执行顺序
SELECT * FROM users
WHERE city = '北京' AND age > 18 OR status = 'vip';
-- 等价于
SELECT * FROM users
WHERE (city = '北京' AND age > 18) OR status = 'vip';
-- 如果需要不同的逻辑,使用括号
SELECT * FROM users
WHERE city = '北京' AND (age > 18 OR status = 'vip');
BETWEEN 范围查询
BETWEEN 用于查询范围内的值,包含边界:
-- 查询价格在 100 到 500 之间的产品
SELECT * FROM products
WHERE price BETWEEN 100 AND 500;
-- 等价于
SELECT * FROM products
WHERE price >= 100 AND price <= 500;
-- 日期范围
SELECT * FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31';
-- NOT BETWEEN
SELECT * FROM products
WHERE price NOT BETWEEN 100 AND 500;
注意
BETWEEN 包含边界值,即 BETWEEN 100 AND 500 等价于 >= 100 AND <= 500。
IN 列表查询
IN 用于匹配多个值中的一个:
-- 查询城市为北京、上海或广州的用户
SELECT * FROM users
WHERE city IN ('北京', '上海', '广州');
-- 等价于
SELECT * FROM users
WHERE city = '北京' OR city = '上海' OR city = '广州';
-- NOT IN
SELECT * FROM users
WHERE city NOT IN ('北京', '上海', '广州');
-- 子查询
SELECT * FROM orders
WHERE user_id IN (SELECT id FROM users WHERE status = 'active');
IN 的优点:
- 语法简洁,易于阅读
- 性能通常优于多个 OR
- 支持子查询
LIKE 模糊匹配
LIKE 用于模糊匹配字符串,支持通配符:
通配符
| 通配符 | 含义 |
|---|---|
% | 匹配任意数量的字符(包括零个) |
_ | 匹配单个字符 |
-- 以"张"开头
SELECT * FROM users WHERE name LIKE '张%';
-- 以"三"结尾
SELECT * FROM users WHERE name LIKE '%三';
-- 包含"小"
SELECT * FROM users WHERE name LIKE '%小%';
-- 第二个字符是"三"
SELECT * FROM users WHERE name LIKE '_三%';
-- 正好三个字符
SELECT * FROM users WHERE name LIKE '___';
NOT LIKE
排除匹配的记录:
-- 查询邮箱不是以 @gmail.com 结尾的用户
SELECT * FROM users WHERE email NOT LIKE '%@gmail.com';
转义通配符
如果需要匹配 % 或 _ 本身,使用转义:
-- 查询包含 % 的产品名
SELECT * FROM products WHERE name LIKE '%\%%';
-- 使用自定义转义字符
SELECT * FROM products WHERE name LIKE '%|%%' ESCAPE '|';
NULL 处理
NULL 需要使用特殊的比较方式:
-- 错误:NULL 不能用 = 比较
SELECT * FROM users WHERE phone = NULL; -- 不会返回任何结果
-- 正确:使用 IS NULL
SELECT * FROM users WHERE phone IS NULL;
-- 查询非 NULL 值
SELECT * FROM users WHERE phone IS NOT NULL;
-- 组合条件
SELECT * FROM users
WHERE phone IS NOT NULL AND city = '北京';
重要
NULL 与任何值的比较都返回 NULL(不是 true 或 false),所以必须使用 IS NULL 或 IS NOT NULL。
复杂条件组合
多条件组合
-- 复杂的业务查询
SELECT * FROM orders
WHERE status = 'completed'
AND total_amount > 1000
AND (payment_method = 'credit_card' OR payment_method = 'alipay')
AND created_at BETWEEN '2024-01-01' AND '2024-12-31';
使用括号控制逻辑
-- 查询 VIP 用户或者(北京地区且年龄大于 18 的用户)
SELECT * FROM users
WHERE status = 'vip'
OR (city = '北京' AND age > 18);
-- 查询(VIP 用户或北京地区)且年龄大于 18 的用户
SELECT * FROM users
WHERE (status = 'vip' OR city = '北京')
AND age > 18;
性能优化建议
1. 使用索引友好的条件
-- 好:可以使用索引
SELECT * FROM users WHERE city = '北京';
-- 差:无法使用索引(以通配符开头)
SELECT * FROM users WHERE name LIKE '%张%';
-- 好:可以使用索引
SELECT * FROM users WHERE name LIKE '张%';
2. 避免在 WHERE 中使用函数
-- 差:索引失效
SELECT * FROM users WHERE YEAR(created_at) = 2024;
-- 好:使用范围查询
SELECT * FROM users
WHERE created_at >= '2024-01-01'
AND created_at < '2025-01-01';
3. 避免隐式类型转换
-- 差:字符串与数字比较(隐式转换)
SELECT * FROM users WHERE phone = 13800138000;
-- 好:类型匹配
SELECT * FROM users WHERE phone = '13800138000';
小结
本章我们学习了:
- 比较运算符(
=、<>、>、<、>=、<=) - 逻辑运算符(
AND、OR、NOT) BETWEEN范围查询IN列表查询LIKE模糊匹配NULL值处理- 复杂条件组合
- 性能优化建议
练习
- 查询价格大于 100 且库存大于 0 的产品
- 查询城市为北京、上海或广州的用户
- 查询姓名以"张"开头的用户
- 查询邮箱为 NULL 的用户
- 查询 2024 年 1 月到 3 月的订单