2.17 sql条件筛选(WHERE、比较运算符、逻辑运算符、BETWEEN、IN、LIKE模糊查询、IS NULL)

2.17 条件筛选(WHERE、比较运算符、逻辑运算符、BETWEEN、IN、LIKE模糊查询、IS NULL)

在电商数据分析中,你几乎不会查全表数据,永远是在筛选特定范围:

  • 只看某天的订单。

  • 只看金额大于500的高价值订单。

  • 只看某个店铺或某个类目的商品。

  • 只看已支付未发货的订单。

WHERE子句就是用来做条件筛选的。这一章我会带你彻底搞懂WHERE的各种用法:比较运算符、逻辑运算符、BETWEENINLIKE模糊查询、空值判断。学完之后,你能精准地从百万行数据中秒级提取你需要的行。

学习前准备:

  • 已完成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执行顺序回顾

  1. FROM:确定数据来源

  2. WHERE:按行筛选

  3. GROUP BYHAVINGSELECTORDER BYLIMIT

在电商数据分析中的核心用途

  • 时间范围筛选(某天、某月、某季度)。

  • 数值区间筛选(金额大于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 分步操作

  1. 先确定要查询的表和列。

  2. 写出不带WHERE的查询,看全量数据。

  3. 加上WHERE和比较条件。

  4. 执行并验证结果行数。

避坑提醒=比较时,字符串要精确匹配(大小写和空格)。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 分步操作

  1. 先写单条件查询验证。

  2. AND/OR组合。

  3. 不确定优先级时加括号。

  4. 执行并验证。

避坑提醒

  • 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 分步操作

  1. 列出需要匹配的值。

  2. IN替换多个OR,提高可读性。

  3. 执行验证。

避坑提醒

  • 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 分步操作

  1. 确定要模糊匹配的模式。

  2. %代表任意长度,_代表单个字符。

  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 分步操作

  1. 确认哪些字段允许NULL。

  2. IS NULLIS NOT NULL筛选。

  3. 注意:NULL不能用=判断。

避坑提醒

  • 在统计中,COUNT(column)会忽略NULL值,COUNT(*)不会。

  • 空字符串''不是NULL,需要用= ''判断。

综合实操案例:618大促高价值订单与异常数据排查

10.1 案例背景

某服饰类目店铺618大促后需要完成以下分析:

  1. 筛选出女装类目中金额≥500元的高价值订单。

  2. 筛选出6月1日至6月3日之间男装专营店的已支付订单。

  3. 找出商品名称中包含"连衣裙"且金额大于300元的订单。

  4. 找出订单状态为空(NULL)的异常订单(假设有)。

  5. 找出金额在100到200之间或金额大于1000的订单。

  6. 找出收货地址(本例没有,改用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查询的灵魂。掌握比较、逻辑、区间、集合、模糊、空值六类条件筛选,你就能从海量数据中精准提取分析所需的数据行。

有问题的评论区留言,我看到会回复。

相关推荐
DaqunChen2 小时前
如何查看对象在数据文件中的分布_DBA_EXTENTS与FILE_ID映射关系
jvm·数据库·python
2301_803538952 小时前
golang如何实现备忘录模式_golang备忘录模式实现方案
jvm·数据库·python
qq_206901392 小时前
如何授予DBA权限_GRANT DBA TO赋予超级管理员角色
jvm·数据库·python
2402_854808372 小时前
Golang怎么实现分布式追踪采样_Golang如何设置采样率控制Trace数据的采集比例【技巧】
jvm·数据库·python
粉嘟小飞妹儿2 小时前
php怎么使用Ice RPC通信_php如何实现跨语言微服务远程调用
jvm·数据库·python
m0_377618232 小时前
C#怎么实现批量邮件发送 C#如何用MailKit批量发送个性化邮件和HTML格式邮件【网络】
jvm·数据库·python
biwenjun9992 小时前
chatBI构建思路拆解(重点是元数据增强)
java·数据库·人工智能
m0_640309302 小时前
宝塔面板如何配置多版本PHP共存_针对不同站点指定环境
jvm·数据库·python
weixin_586061462 小时前
Go 中实现无侵入式方法级执行时间监控的完整实践指南
jvm·数据库·python