MySQL如何筛选订单日期前一年无相同客单的订单?
问题描述
我有一个包含order_date、product code(对应字段code)、customer字段的数据库,示例数据如下:
| 索引 | code | customer | order_date |
|---|---|---|---|
| 1 | CCC | C | 2018-01-01 |
| 2 | AAA | A | 2020-01-01 |
| 3 | CCC | C | 2021-02-02 |
| 4 | CCC | C | 2021-03-03 |
| 5 | DDD | A | 2022-04-04 |
| 6 | FFF | F | 2023-05-05 |
| 7 | FFF | F | 2023-08-08 |
需要编写MySQL查询语句,列出所有满足以下条件的订单:该订单日期前一年内,不存在相同product code和customer的订单。示例期望输出如下:
| 索引 | code | customer | order_date |
|---|---|---|---|
| 1 | CCC | C | 2018-01-01 |
| 2 | AAA | A | 2020-01-01 |
| 3 | CCC | C | 2021-02-02 |
| 5 | DDD | A | 2022-04-04 |
| 6 | FFF | F | 2023-05-05 |
可以看到索引4和7的记录因前一年存在相同product code和customer的订单未被列入,请问如何在MySQL中实现该需求?
解决方案
以下是两种高效实现需求的MySQL查询方法:
方法1:使用NOT EXISTS子查询
这是最直观的写法,通过子查询检查当前订单的code和customer组合,在order_date往前推一年的时间范围内是否存在其他订单。如果不存在,则保留当前订单。
SELECT t1.* FROM your_table t1 WHERE NOT EXISTS ( SELECT 1 FROM your_table t2 WHERE t2.code = t1.code AND t2.customer = t1.customer AND t2.order_date >= DATE_SUB(t1.order_date, INTERVAL 1 YEAR) AND t2.order_date < t1.order_date );
逻辑说明
DATE_SUB(t1.order_date, INTERVAL 1 YEAR)计算当前订单日期往前一年的日期- 子查询筛选出与当前订单
code、customer相同,且订单日期在[前一年日期, 当前订单日期)区间内的记录 - 若子查询无结果返回(即
NOT EXISTS),说明当前订单满足条件,会被选中
方法2:使用LEFT JOIN + IS NULL
与NOT EXISTS逻辑等价,通过左连接匹配符合条件的历史订单,再筛选出无匹配的记录。
SELECT t1.* FROM your_table t1 LEFT JOIN your_table t2 ON t2.code = t1.code AND t2.customer = t1.customer AND t2.order_date >= DATE_SUB(t1.order_date, INTERVAL 1 YEAR) AND t2.order_date < t1.order_date WHERE t2.索引 IS NULL; -- 替换为表中实际的唯一标识字段名
逻辑说明
- 左连接将当前订单与同
code、customer的历史订单(前一年到当前订单日期前)关联 - 若
t2的唯一标识字段为NULL,说明无匹配的历史订单,当前订单符合要求
性能优化建议
为避免全表扫描、提升查询效率,建议在(code, customer, order_date)字段上创建联合索引:
CREATE INDEX idx_code_customer_orderdate ON your_table(code, customer, order_date);
内容的提问来源于stack exchange,提问作者Tibor Pásztor
相关产品推荐
相关产品推荐

