2.17 条件筛选(WHERE、比较运算符、逻辑运算符、BETWEEN、IN、LIKE模糊查询、IS NULL)
在电商数据分析中,你几乎不会查全表数据,永远是在筛选特定范围:
-
只看某天的订单。
-
只看金额大于500的高价值订单。
-
只看某个店铺或某个类目的商品。
-
只看已支付未发货的订单。
WHERE子句就是用来做条件筛选的。这一章我会带你彻底搞懂WHERE的各种用法:比较运算符、逻辑运算符、BETWEEN、IN、LIKE模糊查询、空值判断。学完之后,你能精准地从百万行数据中秒级提取你需要的行。
学习前准备:
-
已完成MySQL安装(参考系列前几章)
-
已安装DBeaver或Navicat
-
准备一个练习数据库,比如
where_demo
学习前环境准备
步骤1:确保MySQL服务已启动。
步骤2:创建练习数据库和表,并插入示例数据。
sql
CREATE DATABASE where_demo
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE where_demo;
-- 订单表
CREATE TABLE orders (
order_id VARCHAR(50) PRIMARY KEY,
user_id INT NOT NULL,
shop_name VARCHAR(50) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
order_status VARCHAR(20) NOT NULL,
create_time DATETIME NOT NULL,
product_name VARCHAR(100)
);
INSERT INTO orders VALUES
('ORD001', 1001, '女装旗舰店', 299.00, '已支付', '2025-06-01 10:00:00', '碎花连衣裙'),
('ORD002', 1002, '女装旗舰店', 189.00, '已取消', '2025-06-01 11:00:00', '纯棉T恤'),
('ORD003', 1003, '男装专营店', 599.00, '已支付', '2025-06-02 09:30:00', '牛仔裤'),
('ORD004', 1001, '女装旗舰店', 399.00, '已支付', '2025-06-03 14:20:00', '雪纺衫'),
('ORD005', 1004, '童装店', 99.00, '已完成', '2025-06-03 16:00:00', '儿童T恤'),
('ORD006', 1005, '女装旗舰店', 1299.00, '已支付', '2025-06-04 08:30:00', '真丝连衣裙'),
('ORD007', 1002, '男装专营店', 89.00, '已取消', '2025-06-04 10:00:00', '休闲短裤'),
('ORD008', 1006, '女装旗舰店', 89.00, '已支付', '2025-06-05 09:00:00', NULL),
('ORD009', 1007, '男装专营店', 259.00, '已支付', '2025-06-05 14:00:00', 'Polo衫');
WHERE条件筛选基础认知
WHERE子句用于过滤行 ,只保留满足条件的记录。它紧跟在FROM之后,在GROUP BY之前执行。
基本语法:
sql
SELECT 列 FROM 表 WHERE 条件;
SQL执行顺序回顾:
-
FROM:确定数据来源 -
WHERE:按行筛选 -
GROUP BY、HAVING、SELECT、ORDER BY、LIMIT
在电商数据分析中的核心用途:
-
时间范围筛选(某天、某月、某季度)。
-
数值区间筛选(金额大于500)。
-
状态筛选(已支付、待发货)。
-
文本匹配(店铺名称、商品名称)。
我的踩坑经历 :我第一次写
WHERE时,把条件写成了WHERE amount > 500 AND order_status = '已支付',结果正确。但后来我写了一个WHERE order_status = '已支付' AND amount > 500,效果一样。但切记:字符串值必须用单引号,数字不用。
比较运算符
4.1 基础语法
| 运算符 | 含义 |
|---|---|
= |
等于 |
> |
大于 |
< |
小于 |
>= |
大于等于 |
<= |
小于等于 |
<> 或 != |
不等于 |
4.2 电商实操案例
案例一:查询金额大于500元的订单
sql
SELECT * FROM orders WHERE amount > 500;
预期结果:ORD003(599)、ORD006(1299)。
案例二:查询金额小于100元的订单
sql
SELECT * FROM orders WHERE amount < 100;
预期结果:ORD005(99)、ORD007(89)、ORD008(89)。
案例三:查询女装旗舰店的订单
sql
SELECT * FROM orders WHERE shop_name = '女装旗舰店';
预期结果:ORD001、ORD002、ORD004、ORD006、ORD008。
案例四:查询不是"已支付"的订单
sql
SELECT * FROM orders WHERE order_status <> '已支付';
-- 或 WHERE order_status != '已支付';
预期结果:ORD002(已取消)、ORD005(已完成)、ORD007(已取消)。
4.3 分步操作
-
先确定要查询的表和列。
-
写出不带
WHERE的查询,看全量数据。 -
加上
WHERE和比较条件。 -
执行并验证结果行数。
避坑提醒 :=比较时,字符串要精确匹配(大小写和空格)。MySQL默认不区分大小写,但区分末尾空格。比如'女装旗舰店 '(多一个空格)匹配不到。
实操避坑提醒 :金额比较时,确保
amount列是数值类型,不能是带货币符号的字符串。否则比较结果可能错误。
逻辑运算符(AND、OR、NOT)
5.1 基础语法
-
AND:所有条件必须同时满足。 -
OR:至少满足一个条件。 -
NOT:取反。
5.2 电商实操案例
案例一:女装旗舰店且金额大于300元的订单
sql
SELECT * FROM orders
WHERE shop_name = '女装旗舰店' AND amount > 300;
预期结果:ORD004(399)、ORD006(1299)。
案例二:女装旗舰店或男装专营店的订单
sql
SELECT * FROM orders
WHERE shop_name = '女装旗舰店' OR shop_name = '男装专营店';
预期结果:除童装店以外的所有订单(ORD001-004,006-009)。
案例三:金额大于500且状态为"已支付",或者金额小于100且状态为"已支付"
sql
SELECT * FROM orders
WHERE (amount > 500 OR amount < 100) AND order_status = '已支付';
注意括号优先级:AND优先级高于OR,所以括号很重要。
预期结果:金额>500且已支付:ORD003(599)、ORD006(1299);金额<100且已支付:ORD008(89) → 共3条。
5.3 分步操作
-
先写单条件查询验证。
-
用
AND/OR组合。 -
不确定优先级时加括号。
-
执行并验证。
避坑提醒:
AND的优先级高于OR,所以条件1 OR 条件2 AND 条件3会被解释为条件1 OR (条件2 AND 条件3)。建议始终用括号明确逻辑。
我的踩坑经历 :我写过
WHERE shop_name = '女装旗舰店' OR shop_name = '男装专营店' AND amount > 500,结果只筛选出男装专营店中金额>500的,女装旗舰店全部返回了。因为AND优先级高,实际是shop_name = '女装旗舰店' OR (shop_name = '男装专营店' AND amount > 500)。加上括号(shop_name = '女装旗舰店' OR shop_name = '男装专营店') AND amount > 500才是我想要的。
BETWEEN区间筛选
6.1 基础语法
sql
WHERE 列 BETWEEN 下界 AND 上界;
等价于列 >= 下界 AND 列 <= 上界,包含边界值。
6.2 电商实操案例
案例一:查询金额在100到300元之间的订单(包含边界)
sql
SELECT * FROM orders WHERE amount BETWEEN 100 AND 300;
预期结果:ORD001(299)、ORD002(189)、ORD004(399? 399不在100-300之间,所以不包括)、ORD009(259) → 实际ORD004=399不在,ORD009=259在。重新确认:ORD001(299)是,ORD002(189)是,ORD009(259)是。ORD004(399)不是。
案例二:查询2025年6月3日到6月4日的订单
sql
SELECT * FROM orders
WHERE create_time BETWEEN '2025-06-03 00:00:00' AND '2025-06-04 23:59:59';
预期结果:ORD004(6月3日14:20)、ORD005(6月3日16:00)、ORD006(6月4日08:30)、ORD007(6月4日10:00)。
6.3 避坑提醒
-
BETWEEN包含边界值,如果不想包含,用>和<组合。 -
日期区间建议用
>= start AND < end + 1,避免漏掉当天的23:59:59之后的记录。例如WHERE create_time >= '2025-06-03' AND create_time < '2025-06-05'。
实操避坑提醒 :
BETWEEN对日期时间类型要小心,因为时间精度可能到秒。最好用>=和<配合。
IN集合筛选
7.1 基础语法
sql
WHERE 列 IN (值1, 值2, ...);
等价于多个OR条件。
7.2 电商实操案例
案例一:查询女装旗舰店和男装专营店的订单
sql
SELECT * FROM orders WHERE shop_name IN ('女装旗舰店', '男装专营店');
案例二:查询订单状态为"已支付"或"已完成"的订单
sql
SELECT * FROM orders WHERE order_status IN ('已支付', '已完成');
预期结果:除已取消外的所有订单。
案例三:查询商品名称为特定几个商品的订单
sql
SELECT * FROM orders WHERE product_name IN ('碎花连衣裙', '牛仔裤', '雪纺衫');
7.3 分步操作
-
列出需要匹配的值。
-
用
IN替换多个OR,提高可读性。 -
执行验证。
避坑提醒:
-
IN列表中的值类型要与列类型一致。 -
如果列表很长,考虑用子查询(后续会讲)。
LIKE模糊查询
8.1 基础语法
sql
WHERE 列 LIKE '模式';
-
%:匹配任意个字符(包括0个)。 -
_:匹配单个字符。
8.2 电商实操案例
案例一:查询商品名称中包含"T恤"的订单
sql
SELECT * FROM orders WHERE product_name LIKE '%T恤%';
预期结果:ORD002(纯棉T恤)、ORD005(儿童T恤)。
案例二:查询商品名称以"雪纺"开头的订单
sql
SELECT * FROM orders WHERE product_name LIKE '雪纺%';
预期结果:ORD004(雪纺衫)。
案例三:查询商品名称中第二个字是"裙"的订单(第一个字任意)
sql
SELECT * FROM orders WHERE product_name LIKE '_裙%';
预期结果:ORD001(碎花连衣裙)、ORD006(真丝连衣裙)。
8.3 分步操作
-
确定要模糊匹配的模式。
-
用
%代表任意长度,_代表单个字符。 -
注意转义字符(如
\%匹配字面%)。
避坑提醒:
-
LIKE默认不区分大小写(MySQL),但区分字符集。 -
以
%开头的模式无法使用索引,性能差。尽量避免在大量数据上用LIKE '%keyword%'。
我的踩坑经历 :我曾用
LIKE '%连衣裙%'去匹配商品名称,结果把"连衣裙"和"雪纺连衣裙"都找到了,但查询跑了10秒。后来加了全文索引才改善。模糊查询前%会导致全表扫描,谨慎使用。
IS NULL / IS NOT NULL空值筛选
9.1 基础语法
sql
WHERE 列 IS NULL;
WHERE 列 IS NOT NULL;
注意:不能写成= NULL,因为NULL代表"未知",任何与NULL的比较结果都是NULL(假)。
9.2 电商实操案例
订单表中有product_name为NULL的行(ORD008)。
案例一:查询商品名称为空的订单
sql
SELECT * FROM orders WHERE product_name IS NULL;
预期结果:ORD008。
案例二:查询商品名称不为空的订单
sql
SELECT * FROM orders WHERE product_name IS NOT NULL;
预期结果:除ORD008外的所有订单。
9.3 分步操作
-
确认哪些字段允许NULL。
-
用
IS NULL或IS NOT NULL筛选。 -
注意:
NULL不能用=判断。
避坑提醒:
-
在统计中,
COUNT(column)会忽略NULL值,COUNT(*)不会。 -
空字符串
''不是NULL,需要用= ''判断。
综合实操案例:618大促高价值订单与异常数据排查
10.1 案例背景
某服饰类目店铺618大促后需要完成以下分析:
-
筛选出女装类目中金额≥500元的高价值订单。
-
筛选出6月1日至6月3日之间男装专营店的已支付订单。
-
找出商品名称中包含"连衣裙"且金额大于300元的订单。
-
找出订单状态为空(NULL)的异常订单(假设有)。
-
找出金额在100到200之间或金额大于1000的订单。
-
找出收货地址(本例没有,改用product_name)为NULL的异常数据。
10.2 分步操作
步骤1:高价值女装订单
sql
SELECT * FROM orders
WHERE shop_name = '女装旗舰店' AND amount >= 500;
预期结果:ORD006(1299)。
步骤2:男装专营店在特定日期的已支付订单
sql
SELECT * FROM orders
WHERE shop_name = '男装专营店'
AND order_status = '已支付'
AND create_time BETWEEN '2025-06-01' AND '2025-06-03';
注意BETWEEN包含6月3日全天,而ORD003是6月2日,ORD009是6月5日,所以只有ORD003符合。
预期结果:ORD003(599)。
步骤3:商品名称包含"连衣裙"且金额>300
sql
SELECT * FROM orders
WHERE product_name LIKE '%连衣裙%' AND amount > 300;
预期结果:ORD006(真丝连衣裙,1299)。ORD001(碎花连衣裙)金额299不大于300,不包含。
步骤4:异常订单(product_name为空)
sql
SELECT * FROM orders WHERE product_name IS NULL;
预期结果:ORD008。
步骤5:金额100-200或大于1000
sql
SELECT * FROM orders
WHERE (amount BETWEEN 100 AND 200) OR amount > 1000;
预期结果:金额100-200:ORD002(189)、ORD007(89? 89不在100-200)、ORD008(89不在)、ORD009(259不在) --- 实际上只有ORD002=189?ORD009=259大于200,不属于。金额>1000:ORD006(1299)。所以结果为ORD002和ORD006。
步骤6:整合所有筛选条件(可选)
sql
SELECT * FROM orders
WHERE (shop_name = '女装旗舰店' AND amount >= 500)
OR (shop_name = '男装专营店' AND order_status = '已支付' AND create_time BETWEEN '2025-06-01' AND '2025-06-03')
OR (product_name LIKE '%连衣裙%' AND amount > 300)
OR product_name IS NULL;
10.3 结果验证
执行以上查询,核对行数和数据是否符合业务预期。
📌 电商数据合规提示 :在筛选用户信息时,如果
user_id能关联到个人,筛选结果中不要直接导出用户ID明细,除非必要。另外,对product_name的模糊查询不会暴露敏感信息,但如果是用户昵称、地址等,要谨慎使用LIKE并限制结果集大小。
本章踩坑清单与合规总结
11.1 新手常见踩坑
| 错误 | 原因 | 正确做法 |
|---|---|---|
WHERE 列 = NULL |
不理解NULL特性 | 用IS NULL |
| 字符串值不加单引号 | 语法错误 | 加单引号 |
LIKE '%keyword'导致全表扫描 |
无法使用索引 | 尽量避免,或使用全文索引 |
AND/OR优先级混淆 |
缺少括号 | 用括号明确逻辑 |
BETWEEN包含边界误用 |
不想要边界值 | 用>=和< |
| 日期区间漏掉当天最后时刻 | 时间精度问题 | 用< '日期+1' |
11.2 性能优化建议
-
尽量在
WHERE中使用索引列。 -
避免在条件中对列做函数转换(如
WHERE DATE(create_time) = '2025-06-01'),会导致索引失效。 -
用
EXPLAIN查看执行计划,确认是否走索引。
结语
WHERE子句是SQL查询的灵魂。掌握比较、逻辑、区间、集合、模糊、空值六类条件筛选,你就能从海量数据中精准提取分析所需的数据行。
有问题的评论区留言,我看到会回复。