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

SQL Server替换NULL值:非循环实现填充最近非空数值

不用WHILE循环填充NULL为最近上一个非空值的T-SQL实现

这是个非常典型的缺失值填充需求,完全不需要用效率较低的WHILE循环,我们可以借助窗口函数来高效实现,下面提供两种适配不同SQL Server版本的方案:

兼容所有SQL Server版本的通用方案

这个方法通过生成分组ID,把连续的NULL和它前面的非空值归为一组,再取组内的非空值来填充:

DECLARE @TABLE TABLE( id int primary key identity(1,1), code int );
INSERT INTO @TABLE VALUES (1),(NULL),(NULL),(NULL),(2),(NULL),(NULL),(NULL),(3),(NULL),(NULL),(NULL);

SELECT 
    id,
    MAX(code) OVER (PARTITION BY group_id) AS filled_code
FROM (
    SELECT 
        id,
        code,
        -- 核心逻辑:每遇到非空code就递增分组ID,将连续NULL归到上一个非空值的组
        SUM(CASE WHEN code IS NOT NULL THEN 1 ELSE 0 END) OVER (ORDER BY id) AS group_id
    FROM @TABLE
) AS subquery;

原理说明

  1. 内层子查询中,SUM(CASE WHEN code IS NOT NULL THEN 1 ELSE 0 END) OVER (ORDER BY id)会生成一个递增的分组ID:
    • 当遇到非空的code时,分组ID加1;
    • 后续的NULL行都会继承这个分组ID,直到下一个非空值出现。
  2. 外层查询通过MAX(code) OVER (PARTITION BY group_id),每个分组里只有一个非空的code值,所以MAX函数会直接取到这个值,填充所有同组的NULL位置。

SQL Server 2022及以上的简化方案

如果你的SQL Server版本是2022或更新,官方支持了IGNORE NULLS参数,可以直接用LAST_VALUE函数一步到位:

DECLARE @TABLE TABLE( id int primary key identity(1,1), code int );
INSERT INTO @TABLE VALUES (1),(NULL),(NULL),(NULL),(2),(NULL),(NULL),(NULL),(3),(NULL),(NULL),(NULL);

SELECT 
    id,
    LAST_VALUE(code) OVER (
        ORDER BY id 
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
        IGNORE NULLS
    ) AS filled_code
FROM @TABLE;

原理说明

LAST_VALUE(code) OVER (...) IGNORE NULLS会在当前行及之前的所有行中,忽略NULL值,直接取最近的那个非空code值,完美匹配你的需求。

内容的提问来源于stack exchange,提问作者EmreB.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 17:42:45