如何用SQL按条件获取每组最新记录与原始审批记录?
SQL实现:按分组提取最新记录及对应原始审批记录
需求说明
从指定数据表中按条件获取每组的最新记录及原始记录。
数据表特性
- 每组可包含多条记录
- 同一基础item对应的
item_name若为变更版本,括号内数字代表变更迭代次数(例如DE-1234(2)是DE-1234的第2次变更) - 记录状态分为*Draft(草稿)和Approved(已审批)*两类
提取规则
- 提取每组最新的记录(按日期排序取最新)
- 若该最新记录状态不为
Approved(即处于变更流程中),则同步提取该组内最新的已审批记录作为原始记录;若最新记录状态为Approved,原始记录字段填NULL
示例数据表
| 分组 | 日期 | item_id | item_name | status | 价格 | 库存 |
|---|---|---|---|---|---|---|
| A | 2022-01-01 | 36FG-34-45 | AB-1234 | Draft | 15 | 100 |
| B | 2022-01-02 | 28AE-23-67 | CD-4567 | Approved | 30 | 120 |
| A | 2022-01-05 | 45RE-12-99 | DE-1234 | Approved | 20 | 300 |
| C | 2022-01-07 | 78ED-14-88 | EA-4532 | Draft | 10 | 500 |
| B | 2022-01-05 | 45AB-16-77 | CD-4567(1) | Draft | 35 | 200 |
| A | 2022-01-03 | 76JJ-98-66 | DE-1234(1) | Approved | 50 | 250 |
| A | 2022-02-02 | 17KL-10-43 | DE-1234(2) | Draft | 12 | 400 |
| C | 2022-03-03 | 97EE-42-17 | AE-2468 | Approved | 25 | 450 |
期望输出
| 分组 | 日期 | item_id | item_name | status | 价格 | 库存 | original_item_id | original_item_name | original_status | original_price | original_stock |
|---|---|---|---|---|---|---|---|---|---|---|---|
| A | 2022-02-02 | 17KL-10-43 | DE-1234(2) | Draft | 12 | 400 | 76JJ-98-66 | DE-1234(1) | Approved | 50 | 250 |
| B | 2022-01-05 | 45AB-16-77 | CD-4567(1) | Draft | 35 | 200 | 28AE-23-67 | CD-4567 | Approved | 30 | 120 |
| C | 2022-03-03 | 97EE-42-17 | AE-2468 | Approved | 25 | 450 | NULL | NULL | NULL | NULL | NULL |
SQL解决方案
思路
- 为每组记录按日期降序排序,标记出每组的最新记录
- 筛选出所有已审批记录,按分组和日期降序排序,标记出每组最新的已审批记录
- 关联两个结果集,根据最新记录的状态决定是否填充原始记录字段
代码实现
WITH latest_records AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY 分组 ORDER BY 日期 DESC) AS rn_latest FROM your_table_name ), latest_approved AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY 分组 ORDER BY 日期 DESC) AS rn_approved FROM your_table_name WHERE status = 'Approved' ) SELECT lr.分组, lr.日期, lr.item_id, lr.item_name, lr.status, lr.价格, lr.库存, CASE WHEN lr.status != 'Approved' THEN la.item_id ELSE NULL END AS original_item_id, CASE WHEN lr.status != 'Approved' THEN la.item_name ELSE NULL END AS original_item_name, CASE WHEN lr.status != 'Approved' THEN la.status ELSE NULL END AS original_status, CASE WHEN lr.status != 'Approved' THEN la.价格 ELSE NULL END AS original_price, CASE WHEN lr.status != 'Approved' THEN la.库存 ELSE NULL END AS original_stock FROM latest_records lr LEFT JOIN latest_approved la ON lr.分组 = la.分组 AND la.rn_approved = 1 WHERE lr.rn_latest = 1 ORDER BY lr.分组;
代码说明
latest_recordsCTE:通过ROW_NUMBER()函数按分组和日期降序排序,标记每组的最新记录(rn_latest=1)latest_approvedCTE:仅筛选已审批记录,同样用ROW_NUMBER()标记每组最新的已审批记录(rn_approved=1)- 主查询:关联两个CTE,取每组最新记录,根据其状态判断是否填充原始记录字段;若最新记录为已审批状态,原始字段统一填
NULL
注意:将代码中的your_table_name替换为实际的数据表名称。
内容的提问来源于stack exchange,提问作者Fowler Fox
相关产品推荐
相关产品推荐

