多表查询:如何获取各里程碑日期对应的前置最新Value值?
如何匹配里程碑对应的最新值记录
需要从两张表中查询每个里程碑对应的目标值,具体需求:
- Start/Finish里程碑:直接取对应日期的Value
- 里程碑1/2:取该里程碑日期之前**最新(日期最大)**的记录的Value
源表数据
表1(值记录表)
| ID | Value | DATE |
|---|---|---|
| A | 12 | 2024/1/1 |
| A | 15 | 2024/1/2 |
| A | 20 | 2024/1/3 |
| A | 22 | 2024/1/4 |
| A | 17 | 2024/1/5 |
| A | 19 | 2024/1/6 |
| B | 7 | 2024/2/1 |
| B | 9 | 2024/2/2 |
| B | 5 | 2024/2/3 |
| B | 8 | 2024/2/4 |
| B | 2 | 2024/2/5 |
表2(里程碑表)
| ID | MileStone | DATE |
|---|---|---|
| A | Start | 2024/1/1 |
| A | 1 | 2024/1/3 |
| A | 2 | 2024/1/5 |
| A | Finish | 2024/1/6 |
| B | Start | 2024/2/1 |
| B | 1 | 2024/2/4 |
| B | Finish | 2024/2/5 |
期望结果
| ID | Value | Milestone |
|---|---|---|
| A | 12 | Start |
| A | 15 | 1 |
| A | 22 | 2 |
| A | 19 | Finish |
| B | 7 | Start |
| B | 5 | 1 |
| B | 2 | Finish |
解决方案
之前用min()函数的思路不对,因为需求是取日期最新的记录,和Value本身的大小无关,必须通过排序日期来筛选目标记录。下面提供两种可行的SQL写法:
方法1:窗口函数(推荐,大数据量性能更优)
SELECT sub.ID, sub.Value, sub.MileStone FROM ( SELECT t2.ID, t2.MileStone, t1.Value, ROW_NUMBER() OVER ( PARTITION BY t2.ID, t2.MileStone ORDER BY t1.DATE DESC ) AS rn FROM 表2 t2 JOIN 表1 t1 ON t1.ID = t2.ID AND t1.DATE <= t2.DATE ) AS sub WHERE rn = 1 ORDER BY sub.ID, CASE sub.MileStone WHEN 'Start' THEN 1 WHEN '1' THEN 2 WHEN '2' THEN 3 WHEN 'Finish' THEN 4 END;
逻辑说明:
- 先将两张表按ID关联,只保留值记录表中日期≤里程碑日期的记录
- 用
ROW_NUMBER()窗口函数按「ID+里程碑」分组,每组内按值记录日期降序排序,最新的记录会被标记为rn=1 - 外层筛选
rn=1的记录,就是每个里程碑对应的目标值 - 最后用
CASE语句保证结果按Start→1→2→Finish的顺序排列
方法2:关联子查询(写法简洁)
SELECT t2.ID, (SELECT t1.Value FROM 表1 t1 WHERE t1.ID = t2.ID AND t1.DATE <= t2.DATE ORDER BY t1.DATE DESC LIMIT 1) AS Value, t2.MileStone FROM 表2 t2 ORDER BY t2.ID, CASE t2.MileStone WHEN 'Start' THEN 1 WHEN '1' THEN 2 WHEN '2' THEN 3 WHEN 'Finish' THEN 4 END;
逻辑说明:
对表2的每一行,通过子查询找到对应ID且日期≤里程碑日期的记录,按日期降序取第一条的Value,直接得到目标结果。
内容的提问来源于stack exchange,提问作者A. Romain
相关产品推荐
相关产品推荐

