SQL需求:将同组内Para_4的Target_Value替换为上方行值之和
计算分组内前置行数值总和填充指定字段的SQL实现
表结构与示例数据
首先我们有一张Parameter_List表,包含以下字段:
Parameter_ID:参数唯一IDParameters_Name:参数名称Target_Value:参数目标值GroupID:分组标识Sequence_No:组内排序序号
原始示例数据如下:
Parameter_ID | Parameters_Name | Target_Value | GroupID | Sequence_No --- | --- | --- | --- | --- 1 | Para_1 | 1000 | 2 | 1 2 | Para_2 | 2000 | 2 | 2 3 | Para_3 | 3000 | 2 | 3 4 | Para_4 | NULL | 2 | 4 5 | Para_5 | 5000 | 2 | 5 6 | Para_1 | 1450 | 3 | 1 7 | Para_2 | 1200 | 3 | 2 8 | Para_4 | NULL | 3 | 3 9 | Para_5 | 3000 | 3 | 4 10 | Para_2 | 3000 | 4 | 1 11 | Para_3 | 4000 | 4 | 2 12 | Para_4 | NULL | 4 | 3
需求说明
我们需要将所有Parameters_Name = 'Para_4'的Target_Value(当前均为NULL),替换为同一GroupID下,Sequence_No小于它的所有行的Target_Value之和。举两个例子:
- GroupID=2时,Para_4的Sequence_No是4,对应前3行的和为
1000+2000+3000=6000 - GroupID=3时,Para_4的Sequence_No是3,对应前2行的和为
1450+1200=2650
预期输出结果如下:
Parameters_Name | Target_Value | GroupID --- | --- | --- Para_1 | 1000 | 2 Para_2 | 2000 | 2 Para_3 | 3000 | 2 Para_4 | 6000 | 2 Para_5 | 5000 | 2 Para_1 | 1450 | 3 Para_2 | 1200 | 3 Para_4 | 2650 | 3 Para_5 | 3000 | 3
解决方案:用窗口函数实现分组累加
这是典型的窗口函数应用场景,我们可以通过SUM() OVER()计算分组内的前置行总和,配合CASE语句完成值的替换,具体SQL代码如下:
SELECT Parameters_Name, CASE WHEN Parameters_Name = 'Para_4' THEN SUM(Target_Value) OVER( PARTITION BY GroupID ORDER BY Sequence_No ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ) ELSE Target_Value END AS Target_Value, GroupID FROM Parameter_List ORDER BY GroupID, Sequence_No;
代码逻辑拆解
PARTITION BY GroupID:将数据按分组ID划分,确保累加计算只在同一组内进行,不会跨组干扰ORDER BY Sequence_No:保证组内数据按序号排序,确保前置行的顺序完全符合业务要求ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING:指定累加范围是从组内第一行到当前行的前一行,完美匹配“Sequence_No小于当前行的所有行”的需求CASE语句:判断当前行是否为Para_4,若是则用计算出的累加和替换原NULL值,否则保留原始Target_Value- 最终排序:按GroupID和Sequence_No排序,输出结果与预期完全对齐
这个方案兼容绝大多数支持窗口函数的SQL数据库(如MySQL 8.0+、PostgreSQL、SQL Server等),执行效率远高于嵌套子查询或自连接的实现方式。
内容的提问来源于stack exchange,提问作者Lokesh
相关产品推荐
相关产品推荐

