You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 15:55:16