MySQL跨多表查询每个客户第N条库存移动记录的创建日期
解决方案:用窗口函数实现分组取第N条记录
这是库存管理场景里很常见的分组排名需求,MySQL 8.0及以上版本提供的窗口函数能完美解决这个问题。咱们直接上可行方案,再拆解细节:
核心思路
- 关联三张表:通过
tableProduct作为中间桥梁,把tableCustomer和tableMovement关联起来,让每条库存移动记录都对应到所属客户。 - 分组排名:用
ROW_NUMBER()窗口函数,按客户ID分组,给每个客户的移动记录按创建日期(或你需要的业务规则)排序并编号。 - 筛选目标记录:从排名结果中挑选出编号等于N的记录,就是每个客户的第N条库存移动记录。
具体SQL代码(以N=25为例)
WITH ranked_movements AS ( SELECT c.customerID, m.createDate, -- 按客户分组,移动记录按创建日期升序排名 ROW_NUMBER() OVER ( PARTITION BY c.customerID ORDER BY m.createDate ASC ) AS movement_rank FROM tableCustomer c -- 关联产品表:匹配客户名下的所有产品 JOIN tableProduct p ON c.customerID = p.customerID -- 关联移动记录表:匹配产品对应的所有库存移动记录 JOIN tableMovement m ON p.productID = m.productID ) -- 筛选出每个客户的第25条移动记录 SELECT customerID, createDate FROM ranked_movements WHERE movement_rank = 25;
关键细节调整
- 排序规则自定义:如果你的业务需要取「最新的第N条」而非「最早的第N条」,把
ORDER BY m.createDate ASC改成ORDER BY m.createDate DESC即可。 - 处理记录不足N条的客户:如果想保留那些移动记录少于N条的客户(对应
createDate显示为NULL),把JOIN换成LEFT JOIN,确保所有客户都被包含:
WITH ranked_movements AS ( SELECT c.customerID, m.createDate, ROW_NUMBER() OVER ( PARTITION BY c.customerID ORDER BY m.createDate ASC ) AS movement_rank FROM tableCustomer c LEFT JOIN tableProduct p ON c.customerID = p.customerID LEFT JOIN tableMovement m ON p.productID = m.productID ) SELECT customerID, createDate FROM ranked_movements WHERE movement_rank = 25;
验证你的示例数据
当N=1时,用你提供的示例数据运行代码,会得到完全符合期望的结果:
| customerID | createDate |
|---|---|
| 123 | 2020-01-25 |
| 124 | 2020-01-28 |
内容的提问来源于stack exchange,提问作者Sebastian
相关产品推荐
相关产品推荐

