SQL实现p_Details表NULL amt字段的同id同month前置change值填充
正确SQL实现方案
你的问题在于LAG()函数仅能获取前一条记录的值,如果前一条的amt同样为NULL,就无法得到有效的填充值。需要使用**向前填充(Forward Fill)**的逻辑,抓取同id、同month分组内,change值小于当前行的最后一个非NULL的amt值。
以下是适配主流数据库的实现方式:
方式一:使用LAST_VALUE结合IGNORE NULLS(支持的数据库:PostgreSQL 11+、MySQL 8.0+、SQL Server 2022+)
SELECT COALESCE(amt, last_non_null_amt) AS amt, id, eff_dt, change, month FROM ( SELECT id, eff_dt, change, month, amt, LAST_VALUE(amt) OVER ( PARTITION BY id, month ORDER BY change ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW IGNORE NULLS ) AS last_non_null_amt FROM p_Details ) t
方式二:兼容旧版本数据库的实现(无IGNORE NULLS支持时)
如果你的数据库不支持IGNORE NULLS,可以通过分组标记非NULL值的区间来实现:
SELECT COALESCE(amt, MAX(amt) OVER (PARTITION BY id, month, grp)) AS amt, id, eff_dt, change, month FROM ( SELECT id, eff_dt, change, month, amt, -- 为每个非NULL amt的区间生成分组标识 SUM(CASE WHEN amt IS NOT NULL THEN 1 ELSE 0 END) OVER ( PARTITION BY id, month ORDER BY change ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS grp FROM p_Details ) t
说明
- 两种方式都是基于
id和month分组,按change升序排序,确保只取当前行之前(change更小)的有效amt。 - 方式一利用
LAST_VALUE的IGNORE NULLS特性,直接跳过NULL值,抓取最近的非NULL值。 - 方式二通过累计计数,将连续的NULL值归到最近的非NULL值所在的分组,再取分组内的最大值(即非NULL的那个值)来填充。
内容的提问来源于stack exchange,提问作者SK ASIF ALI
相关产品推荐
相关产品推荐

