WHERE 条件
WHERE 子句用于过滤查询结果,只返回满足条件的记录。这是 SQL 中非常重要的功能,让你能够精确地控制查询结果。
基本语法
sql
SELECT column1, column2, ...
FROM table_name
WHERE condition;比较运算符
基本比较
sql
-- 等于
SELECT * FROM users WHERE age = 25;
-- 不等于
SELECT * FROM users WHERE age != 25;
-- 大于
SELECT * FROM users WHERE age > 25;
-- 小于
SELECT * FROM users WHERE age < 25;
-- 大于等于
SELECT * FROM users WHERE age >= 25;
-- 小于等于
SELECT * FROM users WHERE age <= 25;示例:查询特定年龄的用户
sql
-- 查询年龄大于等于 25 的用户
SELECT name, age, city
FROM users
WHERE age >= 25;结果:
| name | age | city |
|---|---|---|
| 张三 | 25 | 北京 |
| 李四 | 30 | 上海 |
| 王五 | 28 | 广州 |
| 赵六 | 35 | 北京 |
逻辑运算符
AND 运算符
同时满足多个条件:
sql
-- 查询年龄在 25 到 30 之间且来自北京的用户
SELECT name, age, city
FROM users
WHERE age >= 25
AND age <= 30
AND city = '北京';OR 运算符
满足任一条件:
sql
-- 查询来自北京或上海的用户
SELECT name, city
FROM users
WHERE city = '北京' OR city = '上海';NOT 运算符
否定条件:
sql
-- 查询非北京的用户
SELECT name, city
FROM users
WHERE NOT city = '北京';
-- 等价于
SELECT name, city
FROM users
WHERE city != '北京';运算符优先级
sql
-- 使用括号明确优先级
SELECT name, age, city
FROM users
WHERE (age > 25 AND city = '北京')
OR (age < 25 AND city = '上海');范围查询
BETWEEN 运算符
查询指定范围内的值(包含边界值):
sql
-- 查询年龄在 25 到 30 之间的用户
SELECT name, age
FROM users
WHERE age BETWEEN 25 AND 30;等价于:
sql
SELECT name, age
FROM users
WHERE age >= 25 AND age <= 30;日期范围查询
sql
-- 查询特定日期范围内的订单
SELECT *
FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31';集合查询
IN 运算符
查询值在指定集合中的记录:
sql
-- 查询来自北京、上海、广州的用户
SELECT name, city
FROM users
WHERE city IN ('北京', '上海', '广州');等价于:
sql
SELECT name, city
FROM users
WHERE city = '北京'
OR city = '上海'
OR city = '广州';NOT IN 运算符
sql
-- 查询不是来自北京、上海、广州的用户
SELECT name, city
FROM users
WHERE city NOT IN ('北京', '上海', '广州');子查询中的 IN
sql
-- 查询有订单的用户
SELECT * FROM users
WHERE id IN (SELECT DISTINCT user_id FROM orders);模糊查询
LIKE 运算符
使用通配符进行模糊匹配:
百分号 %
% 匹配任意数量的字符(包括零个):
sql
-- 查询姓"张"的用户
SELECT name FROM users WHERE name LIKE '张%';
-- 查询邮箱以 example.com 结尾的用户
SELECT name, email FROM users
WHERE email LIKE '%@example.com';
-- 查询邮箱包含 'example' 的用户
SELECT name, email FROM users
WHERE email LIKE '%example%';下划线 _
_ 匹配单个字符:
sql
-- 查询用户名第二个字符是'三'的用户
SELECT name FROM users WHERE name LIKE '_三%';
-- 查询邮箱前缀为 5 个字符的用户
SELECT email FROM users WHERE email LIKE '_____@%';示例:灵活的模糊查询
sql
-- 1. 查询名字包含"张"的用户
SELECT * FROM users WHERE name LIKE '%张%';
-- 2. 查询邮箱以 'gmail.com' 结尾的用户
SELECT * FROM users WHERE email LIKE '%@gmail.com';
-- 3. 查询名字长度为 2 的用户
SELECT * FROM users WHERE name LIKE '__';ESCAPE 字符
处理包含特殊字符的字符串:
sql
-- 查询包含百分号的字符串
SELECT * FROM products
WHERE description LIKE '50\% discount' ESCAPE '\';NULL 值处理
IS NULL 和 IS NOT NULL
sql
-- 查询没有填写邮箱的用户
SELECT name, email FROM users WHERE email IS NULL;
-- 查询已填写邮箱的用户
SELECT name, email FROM users WHERE email IS NOT NULL;NULL 的特性
sql
-- NULL 不能使用 = 或 != 比较
-- 错误写法
SELECT * FROM users WHERE email = NULL;
-- 正确写法
SELECT * FROM users WHERE email IS NULL;COALESCE 和 NULL 处理
sql
-- 为 NULL 值提供默认值
SELECT
name,
COALESCE(phone, '未填写电话') AS phone
FROM users;组合条件
复杂条件组合
sql
-- 查询年龄大于 25 且来自北京或上海的用户
SELECT name, age, city
FROM users
WHERE age > 25
AND (city = '北京' OR city = '上海');使用括号分组
sql
-- 注意括号的使用
SELECT name, age, city
FROM users
WHERE (age > 25 AND city = '北京')
OR (age < 25 AND city = '上海');常用条件模式
模式 1:日期过滤
sql
-- 查询最近 7 天的订单
SELECT * FROM orders
WHERE order_date >= DATE_SUB(NOW(), INTERVAL 7 DAY);
-- 查询本月的订单
SELECT * FROM orders
WHERE MONTH(order_date) = MONTH(NOW())
AND YEAR(order_date) = YEAR(NOW());模式 2:数值范围
sql
-- 查询价格在 100 到 500 之间的商品
SELECT * FROM products
WHERE price BETWEEN 100 AND 500;模式 3:多条件组合
sql
-- 查询活跃且近期登录的用户
SELECT * FROM users
WHERE status = 'active'
AND last_login >= DATE_SUB(NOW(), INTERVAL 30 DAY)
AND email IS NOT NULL;WHERE vs HAVING
WHERE
- 在分组前过滤
- 不能使用聚合函数
HAVING
- 在分组后过滤
- 可以使用聚合函数
示例对比
sql
-- 使用 WHERE(正确)
SELECT city, COUNT(*)
FROM users
WHERE age > 18
GROUP BY city;
-- 使用 HAVING
SELECT city, COUNT(*)
FROM users
GROUP BY city
HAVING COUNT(*) > 5;性能优化
1. 使用索引
sql
-- 为常用查询条件创建索引
CREATE INDEX idx_user_age ON users(age);
CREATE INDEX idx_user_city ON users(city);2. 避免在 WHERE 中使用函数
sql
-- 不推荐:在列上使用函数
SELECT * FROM users
WHERE YEAR(created_at) = 2024;
-- 推荐:使用范围查询
SELECT * FROM users
WHERE created_at >= '2024-01-01'
AND created_at < '2025-01-01';3. 使用 EXISTS 而不是 IN
sql
-- 不推荐:IN 子查询
SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders);
-- 推荐:EXISTS 子查询
SELECT * FROM users u
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);实战示例
示例 1:用户筛选
sql
-- 查询 25-35 岁、来自北京或上海的活跃用户
SELECT
name,
age,
city
FROM users
WHERE age BETWEEN 25 AND 35
AND city IN ('北京', '上海')
AND status = 'active'
ORDER BY age;示例 2:订单查询
sql
-- 查询本月金额大于 500 的订单
SELECT
order_id,
user_id,
total_amount,
order_date
FROM orders
WHERE order_date >= DATE_FORMAT(NOW(), '%Y-%m-01')
AND total_amount > 500
ORDER BY total_amount DESC;示例 3:商品搜索
sql
-- 搜索名称或描述包含关键词的商品
SELECT
name,
price,
stock
FROM products
WHERE name LIKE '%关键词%'
OR description LIKE '%关键词%'
ORDER BY price;常见错误
错误 1:混淆 = 和 ==
sql
-- 错误
SELECT * FROM users WHERE age == 25;
-- 正确
SELECT * FROM users WHERE age = 25;错误 2:字符串没有引号
sql
-- 错误
SELECT * FROM users WHERE city = 北京;
-- 正确
SELECT * FROM users WHERE city = '北京';错误 3:NULL 使用比较运算符
sql
-- 错误
SELECT * FROM users WHERE email = NULL;
-- 正确
SELECT * FROM users WHERE email IS NULL;小结
本章介绍了 WHERE 子句的各种用法:
- 比较运算符:=, !=, >, <, >=, <=
- 逻辑运算符:AND, OR, NOT
- 范围查询:BETWEEN
- 集合查询:IN, NOT IN
- 模糊查询:LIKE, %, _
- NULL 处理:IS NULL, IS NOT NULL
- 组合条件:使用括号分组
- WHERE vs HAVING:过滤时机不同
- 性能优化:使用索引、避免函数、使用 EXISTS
WHERE 子句是 SQL 查询的核心,掌握各种条件过滤方法,可以精确地控制查询结果。
下一步: 学习 排序和分页,学习如何对查询结果进行排序和分页。