You need to enable JavaScript to run this app. 在 SQL Server 中按 ID 分组并保留数据最多的一行
优惠活动
大模型
产品
解决方案
定价
更多

在 SQL Server 中按 ID 分组并保留数据最多的一行

实现方法

使用两层公用表达式(CTE)配合ROW_NUMBER()窗口函数实现,逻辑清晰,且天然支持全NULL分组返回一行的要求。

完整代码

假设表名为dbo.YourTable,按实际列名补全中间省略的27个数据列即可:

WITH RowWithNonNullCount AS (
    SELECT
        *,
        -- 统计当前行30个数据列的非NULL数量
        (
            CASE WHEN [Data A] IS NOT NULL THEN 1 ELSE 0 END +
            CASE WHEN [Data B] IS NOT NULL THEN 1 ELSE 0 END +
            -- 此处依次补全 Data C ~ Data29 的判断
            CASE WHEN [Data30] IS NOT NULL THEN 1 ELSE 0 END
        ) AS NonNullCount
    FROM dbo.YourTable
),
RankedRows AS (
    SELECT
        *,
        ROW_NUMBER() OVER (
            PARTITION BY ID
            ORDER BY NonNullCount DESC
            -- 若表有主键/自增列,取消下一行注释,保证并列时结果固定
            -- , TablePrimaryKey ASC
        ) AS RowRank
    FROM RowWithNonNullCount
)
-- 显式选择业务列,排除计算用的辅助列
SELECT
    ID,
    City,
    Country,
    [Data A],
    [Data B],
    -- 此处依次补全 Data C ~ Data29
    [Data30]
FROM RankedRows
WHERE RowRank = 1;

逻辑说明

  • 第一层CTE逐行计算30个数据列的非NULL总数,判断逻辑只需编写一次
  • ROW_NUMBER()通过PARTITION BY ID将同ID的行划为一组,组内按非NULL数量降序编号,非NULL列最多的行编号为1
  • 若同ID所有数据列全为NULL,所有行计数值均为0,窗口函数依然会生成从1开始的连续编号,不会丢失分组
  • 最终过滤RowRank = 1即可保证每个ID只返回一行

注意事项

  • 列名含空格、特殊字符时,必须用SQL Server的方括号[]包裹,比如示例中的[Data A]
  • 并列场景下如果需要固定返回规则(比如示例要求取第一行),建议追加表的主键、自增列作为第二排序条件;不要依赖默认物理顺序,索引重建、数据更新都可能导致默认顺序变化
  • 如果业务上把空字符串''也视为空值,把判断条件改为WHEN 列名 IS NOT NULL AND 列名 <> '' THEN 1即可
  • 30个列必须显式写出,表结构固定的场景下这是性能最稳定、可读性最好的实现,不要为固定结构的表使用动态SQL
  • 不推荐“先分组求最大非空数再回表关联”的写法:该方案遇到并列时会返回多行,且会产生额外表扫描,性能更差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 06:45:03