Skip to content

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;

结果:

nameagecity
张三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 查询的核心,掌握各种条件过滤方法,可以精确地控制查询结果。

下一步: 学习 排序和分页,学习如何对查询结果进行排序和分页。