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

SQL Server中若前列为NULL,能否将列数据向左移动填充空列?

在SQL Server中实现非NULL值左移填充

当然可以实现!针对你这种需要把保单类型列里的非NULL值向左移动、消除左侧NULL的场景,在SQL Server里有几种高效的方案,我结合你的示例数据来详细说明:

先看你的示例数据

首先我把你的测试数据整理成可执行的SQL脚本,方便验证:

CREATE TABLE #TempPolicy (
    Pol_Ref VARCHAR(20),
    Pol_Mix VARCHAR(20),
    Pol_1_Type VARCHAR(10),
    Pol_2_Type VARCHAR(10),
    Pol_3_Type VARCHAR(10),
    Pol_4_Type VARCHAR(10)
);

INSERT INTO #TempPolicy VALUES
('XXXXXXSW01', 'Car', NULL, 'PC', NULL, NULL),
('XXXXXXSW02', 'Modern', NULL, 'PC', 'MB', NULL),
('XXXXXXSW01', 'Car', NULL, NULL, 'PC', NULL),
('XXXXXXSW03', 'Modern', 'PC', NULL, 'MB', NULL);

方法一:UNPIVOT + PIVOT(推荐,高效处理大数据)

这个方法通过列转行过滤掉NULL,再行转列重新排序填充,适合处理数万行的数据集:

WITH UnpivotedData AS (
    SELECT 
        Pol_Ref,
        Pol_Mix,
        PolicyType,
        -- 按原列顺序给非NULL值分配新的序号
        ROW_NUMBER() OVER (PARTITION BY Pol_Ref, Pol_Mix ORDER BY Seq) AS NewColumnSeq
    FROM #TempPolicy
    -- 将4个类型列转成多行,每行对应一个类型值
    UNPIVOT (
        PolicyType FOR Seq IN (Pol_1_Type, Pol_2_Type, Pol_3_Type, Pol_4_Type)
    ) AS UnpivotStep
    WHERE PolicyType IS NOT NULL -- 过滤掉NULL值
)
SELECT 
    Pol_Ref,
    Pol_Mix,
    -- 按新序号重新分配到Pol_1到Pol_4列
    MAX(CASE WHEN NewColumnSeq = 1 THEN PolicyType END) AS Pol_1_Type,
    MAX(CASE WHEN NewColumnSeq = 2 THEN PolicyType END) AS Pol_2_Type,
    MAX(CASE WHEN NewColumnSeq = 3 THEN PolicyType END) AS Pol_3_Type,
    MAX(CASE WHEN NewColumnSeq = 4 THEN PolicyType END) AS Pol_4_Type
FROM UnpivotedData
GROUP BY Pol_Ref, Pol_Mix
ORDER BY Pol_Ref;

执行后你会得到想要的结果:所有非NULL的保单类型都会向左填充,Pol_1_Type再也不会出现NULL。

方法二:STRING_AGG + STRING_SPLIT(适合SQL Server 2017+)

如果你的SQL Server版本是2017及以上,可以用字符串聚合拆分的方式实现,逻辑更直观:

WITH AggregatedTypes AS (
    SELECT 
        Pol_Ref,
        Pol_Mix,
        -- 把每个分组的非NULL类型按原顺序拼接成字符串
        STRING_AGG(PolicyType, ',') WITHIN GROUP (ORDER BY Seq) AS PolicyTypeList
    FROM #TempPolicy
    UNPIVOT (
        PolicyType FOR Seq IN (Pol_1_Type, Pol_2_Type, Pol_3_Type, Pol_4_Type)
    ) AS UnpivotStep
    WHERE PolicyType IS NOT NULL
    GROUP BY Pol_Ref, Pol_Mix
),
SplitTypes AS (
    SELECT 
        Pol_Ref,
        Pol_Mix,
        value AS PolicyType,
        -- 给拆分后的类型分配序号
        ROW_NUMBER() OVER (PARTITION BY Pol_Ref, Pol_Mix ORDER BY (SELECT NULL)) AS NewColumnSeq
    FROM AggregatedTypes
    -- 把拼接的字符串拆分成多行
    CROSS APPLY STRING_SPLIT(PolicyTypeList, ',')
)
SELECT 
    Pol_Ref,
    Pol_Mix,
    MAX(CASE WHEN NewColumnSeq = 1 THEN PolicyType END) AS Pol_1_Type,
    MAX(CASE WHEN NewColumnSeq = 2 THEN PolicyType END) AS Pol_2_Type,
    MAX(CASE WHEN NewColumnSeq = 3 THEN PolicyType END) AS Pol_3_Type,
    MAX(CASE WHEN NewColumnSeq = 4 THEN PolicyType END) AS Pol_4_Type
FROM SplitTypes
GROUP BY Pol_Ref, Pol_Mix
ORDER BY Pol_Ref;

注意事项

  • 两种方法都能高效处理数万行数据,其中UNPIVOT/PIVOT的性能更优,因为避免了字符串处理的额外开销;
  • 如果你的实际表中还有其他需要保留的列,只需要在CTE和GROUP BY子句中加入对应的列即可;
  • 确保ORDER BY Seq的顺序和原列的顺序一致(Pol_1_Type在前,Pol_4_Type在后),这样左移后的顺序才符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:49:45