MySQL高效查询:特定代理ID与日期范围的去重订单ID获取
需求与背景
表结构关联
sales_order(订单头表):存储订单基础信息,核心字段包括order_id(订单主键)、creation_date(订单创建日期)sales_order_item(订单行表):存储订单明细数据,核心字段包括entity_id(关联订单头的ID,与sales_order.order_id对应)、item(商品编码)、agent_id(代理ID)- 关联规则:
sales_order.order_id = sales_order_item.entity_id
示例数据
sales_order表
| order_id | creation_date |
|---|---|
| 34....... | 2022-02-01 |
| 45....... | 2022-04-12 |
| 56....... | 2022-07-22 |
| 67....... | 2022-08-05 |
sales_order_item表
| entity_id | item | agent_id |
|---|---|---|
| 34....... | 3242344213 | 09 |
| 34....... | 3442344213 | 09 |
| 34....... | 2342344213 | 09 |
| 45....... | 3142344213 | 09 |
业务需求
提取满足以下条件的去重订单ID:
- 代理ID为
09 - 订单创建日期在
2022-02-01至2022-05-20之间
预期结果:34、45
最高性能实现方案
1. 最优SQL语句
优先采用**半连接(EXISTS)**方案,它会在找到匹配的订单行后立即停止扫描,避免不必要的全量关联和后续去重开销:
SELECT a.order_id FROM sales_order a WHERE a.creation_date BETWEEN '2022-02-01' AND '2022-05-20' AND EXISTS ( SELECT 1 FROM sales_order_item b WHERE b.entity_id = a.order_id AND b.agent_id = '09' );
如果更习惯使用JOIN写法,也可以用DISTINCT配合索引优化,但性能略逊于EXISTS:
SELECT DISTINCT a.order_id FROM sales_order a JOIN sales_order_item b ON a.order_id = b.entity_id WHERE b.agent_id = '09' AND a.creation_date BETWEEN '2022-02-01' AND '2022-05-20';
2. 关键索引优化
索引是提升性能的核心,必须创建以下复合索引实现覆盖扫描(无需回表查询实际数据):
- 给
sales_order表创建:CREATE INDEX idx_sales_order_date_id ON sales_order(creation_date, order_id);
作用:按日期范围快速筛选订单,直接从索引中获取order_id,无需访问表数据。 - 给
sales_order_item表创建:CREATE INDEX idx_sales_item_agent_entity ON sales_order_item(agent_id, entity_id);
作用:先按agent_id过滤,再快速匹配对应的订单ID,避免全表扫描订单行。
性能优势总结
- 半连接逻辑减少了冗余的行关联操作,避免JOIN后大量重复数据的去重计算;
- 复合索引覆盖了查询所需的所有字段,消除了回表开销,大幅缩短查询时间。
内容的提问来源于stack exchange,提问作者JustToKnow
相关产品推荐
相关产品推荐

