如何实现LAG函数自引用,批量向下填充表中NULL字段?
问题解答
核心结论
LAG函数不能实现自引用,而且它本身也无法处理连续多行NULL的向下填充需求:
- SQL解析时,SELECT子句中定义的字段别名(比如你写的
Split_Name)无法在同层级的窗口函数或其他字段中直接引用,这是你代码报错的原因。 - LAG默认仅能获取前一行的数据,就算你改成引用原字段
Split_Name_In_Heading,也只能填充紧邻的下一行,再往后的NULL行依然无法拿到有效值。
通用SQL解决方案
要实现将有效值向下填充至所有后续NULL行,直到遇到新有效值为止,通用的做法是先给每个有效值及其后续NULL行分配同一个组ID,再在组内提取有效值。
兼容所有SQL数据库的写法
WITH GroupedData AS ( SELECT Split_Name_In_Heading, ID, -- 生成组ID:每遇到非NULL值,组ID递增,将有效值和后续NULL归为一组 SUM(CASE WHEN Split_Name_In_Heading IS NOT NULL THEN 1 ELSE 0 END) OVER (ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS GroupID FROM #Clean_List ) SELECT -- 组内取唯一的非NULL值(MAX/ MIN都可以,因为组内只有一个有效值) MAX(REPLACE(Split_Name_In_Heading, ' (contd)', '')) OVER (PARTITION BY GroupID) AS Split_Name, Split_Name_In_Heading, ID FROM GroupedData ORDER BY ID;
简洁版(需数据库支持IGNORE NULLS)
如果你的数据库支持IGNORE NULLS参数(比如SQL Server 2022+、PostgreSQL 11+、Oracle),可以直接用LAST_VALUE函数实现,代码更简洁:
SELECT LAST_VALUE(REPLACE(Split_Name_In_Heading, ' (contd)', '')) OVER (ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) IGNORE NULLS AS Split_Name, Split_Name_In_Heading, ID FROM #Clean_List ORDER BY ID;
效果说明
以上两种写法都会将示例数据中的Central Scheduling填充到所有后续的NULL行,最终结果如下:
| Split_Name | Split_Name_In_Heading | ID |
|---|---|---|
| Central Scheduling | Central Scheduling (contd) | 171081 |
| Central Scheduling | NULL | 171083 |
| Central Scheduling | NULL | 171088 |
| Central Scheduling | NULL | 171091 |
| Central Scheduling | NULL | 171094 |
| Central Scheduling | NULL | 171097 |
内容的提问来源于stack exchange,提问作者John L. Edwards
相关产品推荐
相关产品推荐

