前面介绍了在 where 语句中使用比较运算符、范围查询(between)、集合查询(in)、空值判断(is null)和模糊查询(like)实现数据过滤。
下面将介绍使用 AND、OR 和 NOT 将多个条件进行组合,实现更为复杂的过滤条件:
AND 是逻辑与运算符,用于拼接两个及以上查询条件。只有所有条件同时成立时,整行数据才会被筛选出来。任意一个条件不满足,该行都会被过滤。主要用在 WHERE、HAVING、CASE WHEN等需要条件判断的场景。
语法格式:条件A AND 条件B
| 条件 A 结果 | 条件 B 结果 | AND 最终结果 |
|---|---|---|
| 成立(真) | 成立(真) | ✅️成立 |
| 成立(真) | 不成立(假) | 不成立 |
| 不成立(假) | 成立(真) | 不成立 |
| 不成立(假) | 不成立(假) | 不成立 |
简单示例:
-- 查询年龄等于22,用户姓名以“zheng”开头的用户信息
mysql> select * from users where user_age=22 and username like 'zheng%';
+---------+-------------+----------+---------------------+-------------+---------------------+
| user_id | username | user_age | email | phone | created_at |
+---------+-------------+----------+---------------------+-------------+---------------------+
| 9 | zheng_shiyi | 22 | zheng11@example.com | 13800138009 | 2026-07-29 13:55:25 |
+---------+-------------+----------+---------------------+-------------+---------------------+
1 row in set (0.00 sec)
OR 是逻辑或运算符,用于拼接多个查询条件,任意一个条件成立,整条判定结果即为成立,只要满足其中一项数据就会被筛选出来。主要用于 WHERE、HAVING、CASE WHEN 等需要多条件择一匹配的场景。
语法格式:条件1 OR 条件2 OR 条件3 ...
| 条件 A | 条件 B | A OR B 最终结果 |
|---|---|---|
| 真 | 真 | ✅️真 |
| 真 | 假 | ✅️真 |
| 假 | 真 | ✅️真 |
| 假 | 假 | 假 |
简单示例:
-- 查询年龄等于50、或用户姓名以“zheng”开头的用户信息
mysql> select * from users where user_age=50 or username like 'zheng%';
+---------+-------------+----------+---------------------+-------------+---------------------+
| user_id | username | user_age | email | phone | created_at |
+---------+-------------+----------+---------------------+-------------+---------------------+
| 8 | wu_shi | 50 | wushi@example.com | 13800138008 | 2026-07-29 13:55:25 |
| 9 | zheng_shiyi | 22 | zheng11@example.com | 13800138009 | 2026-07-29 13:55:25 |
+---------+-------------+----------+---------------------+-------------+---------------------+
2 rows in set (0.00 sec)mysql 广告位
NOT 意为取反、非,对紧随其后的查询条件进行真假翻转:
条件成立 → 使用NOT后不成立
条件不成立 → 使用NOT后成立
NOT 常搭配 WHERE、HAVING、CASE WHEN 等场景做条件反转。
运算优先级:NOT 优先级高于 AND、OR,执行顺序:NOT > AND > OR。
多条件混杂时建议用小括号限定判断范围,避免逻辑错乱。
语法格式:NOT 条件
简单示例:
-- 查询用户名不以“z”开头的用户信息
mysql> select * from users where username not like 'z%';
+---------+------------+----------+--------------------+-------------+---------------------+
| user_id | username | user_age | email | phone | created_at |
+---------+------------+----------+--------------------+-------------+---------------------+
| 2 | li_si | 28 | lisi@example.com | 13800138002 | 2026-07-29 13:55:25 |
| 3 | wang_wu | 35 | wangwu@example.com | 13800138003 | 2026-07-29 13:55:25 |
| 5 | qian_qi | 42 | qianqi@example.com | 13800138005 | 2026-07-29 13:55:25 |
| 6 | sun_ba | 26 | sunba@example.com | 13800138006 | 2026-07-29 13:55:25 |
| 8 | wu_shi | 50 | wushi@example.com | 13800138008 | 2026-07-29 13:55:25 |
| 10 | chen_shier | 38 | chen12@example.com | 13800138010 | 2026-07-29 13:55:25 |
+---------+------------+----------+--------------------+-------------+---------------------+
6 rows in set (0.00 sec)注意,NOT 语句存在几个关键特性与避坑要点,使用时要谨慎:
NULL 代表未知值,NOT NULL结果依旧是未知,不会判定为真 / 假。例如:
-- 无效写法,查不出任何数据
mysql> select * from users where not user_age = null;
Empty set (0.00 sec)
-- 正确写法
mysql> select * from users where not user_age is null;
+---------+-------------+----------+----------------------+-------------+---------------------+
| user_id | username | user_age | email | phone | created_at |
+---------+-------------+----------+----------------------+-------------+---------------------+
| 1 | zhang_san | 23 | zhangsan@example.com | 13800138001 | 2026-07-29 13:55:25 |
| 2 | li_si | 28 | lisi@example.com | 13800138002 | 2026-07-29 13:55:25 |
| 3 | wang_wu | 35 | wangwu@example.com | 13800138003 | 2026-07-29 13:55:25 |
| 4 | zhao_liu | 19 | zhaoliu@example.com | NULL | 2026-07-29 13:55:25 |
| 5 | qian_qi | 42 | qianqi@example.com | 13800138005 | 2026-07-29 13:55:25 |
| 6 | sun_ba | 26 | sunba@example.com | 13800138006 | 2026-07-29 13:55:25 |
| 7 | zhou_jiu | 31 | zhoujiu@example.com | NULL | 2026-07-29 13:55:25 |
| 8 | wu_shi | 50 | wushi@example.com | 13800138008 | 2026-07-29 13:55:25 |
| 9 | zheng_shiyi | 22 | zheng11@example.com | 13800138009 | 2026-07-29 13:55:25 |
| 10 | chen_shier | 38 | chen12@example.com | 13800138010 | 2026-07-29 13:55:25 |
+---------+-------------+----------+----------------------+-------------+---------------------+
10 rows in set (0.00 sec)多层取反会大幅降低 SQL 可读性,能正向判断优先正向书写。例如:
-- 不推荐:双重取反绕逻辑
mysql> select * from users where not not user_age >= 35;
+---------+------------+----------+--------------------+-------------+---------------------+
| user_id | username | user_age | email | phone | created_at |
+---------+------------+----------+--------------------+-------------+---------------------+
| 3 | wang_wu | 35 | wangwu@example.com | 13800138003 | 2026-07-29 13:55:25 |
| 5 | qian_qi | 42 | qianqi@example.com | 13800138005 | 2026-07-29 13:55:25 |
| 8 | wu_shi | 50 | wushi@example.com | 13800138008 | 2026-07-29 13:55:25 |
| 10 | chen_shier | 38 | chen12@example.com | 13800138010 | 2026-07-29 13:55:25 |
+---------+------------+----------+--------------------+-------------+---------------------+
4 rows in set (0.00 sec)
-- 推荐直接正向判断
mysql> select * from users where not not user_age >= 35;“NOT 字段=值”语义上等价于 “字段!=值”、“字段<>值”
简单不等判断优先用 !=
需要对区间、集合、模糊查询、整组条件取反时,只能用 NOT
-- 不加括号:先执行 not user_age=50,再执行 and user_age>35
mysql> select * from users where not user_age=50 and user_age>35;
+---------+------------+----------+--------------------+-------------+---------------------+
| user_id | username | user_age | email | phone | created_at |
+---------+------------+----------+--------------------+-------------+---------------------+
| 5 | qian_qi | 42 | qianqi@example.com | 13800138005 | 2026-07-29 13:55:25 |
| 10 | chen_shier | 38 | chen12@example.com | 13800138010 | 2026-07-29 13:55:25 |
+---------+------------+----------+--------------------+-------------+---------------------+
2 rows in set (0.00 sec)
-- 加括号:整体对 user_age=50 and user_age>35 取反
mysql> select * from users where not (user_age=50 and user_age>35);
+---------+-------------+----------+----------------------+-------------+---------------------+
| user_id | username | user_age | email | phone | created_at |
+---------+-------------+----------+----------------------+-------------+---------------------+
| 1 | zhang_san | 23 | zhangsan@example.com | 13800138001 | 2026-07-29 13:55:25 |
| 2 | li_si | 28 | lisi@example.com | 13800138002 | 2026-07-29 13:55:25 |
| 3 | wang_wu | 35 | wangwu@example.com | 13800138003 | 2026-07-29 13:55:25 |
| 4 | zhao_liu | 19 | zhaoliu@example.com | NULL | 2026-07-29 13:55:25 |
| 5 | qian_qi | 42 | qianqi@example.com | 13800138005 | 2026-07-29 13:55:25 |
| 6 | sun_ba | 26 | sunba@example.com | 13800138006 | 2026-07-29 13:55:25 |
| 7 | zhou_jiu | 31 | zhoujiu@example.com | NULL | 2026-07-29 13:55:25 |
| 9 | zheng_shiyi | 22 | zheng11@example.com | 13800138009 | 2026-07-29 13:55:25 |
| 10 | chen_shier | 38 | chen12@example.com | 13800138010 | 2026-07-29 13:55:25 |
+---------+-------------+----------+----------------------+-------------+---------------------+
9 rows in set (0.00 sec)两句执行逻辑完全不同,复杂条件务必加括号约束范围。
逻辑运算符的优先级:NOT > AND > OR
-- 这个查询的逻辑是:查询年龄大于30且用户名以wu开头的用户信息,和用户名以zhang开头的用户信息
mysql> select * from users where user_age>30 and username like 'wu%' or username like 'zhang%';
+---------+-----------+----------+----------------------+-------------+---------------------+
| user_id | username | user_age | email | phone | created_at |
+---------+-----------+----------+----------------------+-------------+---------------------+
| 1 | zhang_san | 23 | zhangsan@example.com | 13800138001 | 2026-07-29 13:55:25 |
| 8 | wu_shi | 50 | wushi@example.com | 13800138008 | 2026-07-29 13:55:25 |
+---------+-----------+----------+----------------------+-------------+---------------------+
2 rows in set (0.00 sec)
-- 为了避免混淆,建议用括号明确优先级
mysql> select * from users where (user_age>30 and username like 'wu%') or username like 'zhang%';
+---------+-----------+----------+----------------------+-------------+---------------------+
| user_id | username | user_age | email | phone | created_at |
+---------+-----------+----------+----------------------+-------------+---------------------+
| 1 | zhang_san | 23 | zhangsan@example.com | 13800138001 | 2026-07-29 13:55:25 |
| 8 | wu_shi | 50 | wushi@example.com | 13800138008 | 2026-07-29 13:55:25 |
+---------+-----------+----------+----------------------+-------------+---------------------+
2 rows in set (0.00 sec)注意,为了避免混淆建议添加括号明确优先级。