You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在SQL Server中使用UPDATE和DELETE合并并删除重复行

在SQL Server中实现合并重复行并删除冗余数据的方案

嘿,这个需求我之前处理过类似的,咱们可以分更新合并删除冗余两步来完成,下面是具体的操作方法和代码示例:

第一步:合并重复行的deviceType到保留行

首先,咱们需要把同一codenametype分组下的所有deviceType合并到该组的某一行(比如保留id最小的那行)。这里可以用CTE结合窗口函数来定位目标行,再用字符串拼接的方式合并deviceType:

方法1:适用于SQL Server 2017及以上(使用STRING_AGG)

-- 先创建测试表(如果你的表已经存在可以跳过这步)
CREATE TABLE TestTable (
    id INT,
    code INT,
    name VARCHAR(50),
    type INT,
    deviceType VARCHAR(50)
);

-- 插入测试数据
INSERT INTO TestTable VALUES
(1, 23, 'xyz', 0, 'web'),
(2, 23, 'xyz', 0, 'mobile'),
(3, 24, 'xyzc', 0, 'web'),
(4, 25, 'xyzc', 0, 'web');

-- 使用CTE更新合并deviceType
WITH GroupedData AS (
    SELECT 
        id,
        code,
        name,
        type,
        deviceType,
        -- 给每组的行按id排序,标记主行(id最小的为1)
        ROW_NUMBER() OVER (PARTITION BY code, name, type ORDER BY id) AS RowNum,
        -- 合并当前组的所有deviceType,用&分隔
        STRING_AGG(deviceType, '&') OVER (PARTITION BY code, name, type) AS CombinedDeviceType
    FROM TestTable
)
UPDATE GroupedData
SET deviceType = CombinedDeviceType
WHERE RowNum = 1; -- 只更新每组的主行

方法2:适用于SQL Server 2016及以下(使用FOR XML PATH拼接)

如果你的SQL Server版本较低,不支持STRING_AGG,可以用传统的FOR XML PATH方式拼接字符串:

WITH GroupedData AS (
    SELECT 
        t1.id,
        t1.code,
        t1.name,
        t1.type,
        -- 拼接当前组的deviceType
        STUFF((
            SELECT '&' + t2.deviceType
            FROM TestTable t2
            WHERE t2.code = t1.code AND t2.name = t1.name AND t2.type = t1.type
            FOR XML PATH(''), TYPE
        ).value('.', 'VARCHAR(MAX)'), 1, 1, '') AS CombinedDeviceType
    FROM TestTable t1
    -- 只保留每组id最小的行作为更新目标
    WHERE t1.id = (SELECT MIN(id) FROM TestTable WHERE code = t1.code AND name = t1.name AND type = t1.type)
)
UPDATE GroupedData
SET deviceType = CombinedDeviceType;

第二步:删除冗余的重复行

更新完成后,咱们需要删掉每组中除主行(id最小的行)之外的其他重复行:

WITH DuplicateRows AS (
    SELECT 
        id,
        ROW_NUMBER() OVER (PARTITION BY code, name, type ORDER BY id) AS RowNum
    FROM TestTable
)
DELETE FROM DuplicateRows
WHERE RowNum > 1; -- 删除每组中序号大于1的行

验证结果

执行完以上步骤后,查询表数据就能得到你想要的结果:

SELECT * FROM TestTable;

输出:

id | code | name | type | deviceType
---+------+------+------+-----------
1  | 23   | xyz  | 0    | web&mobile
3  | 24   | xyzc | 0    | web
4  | 25   | xyzc | 0    | web

注意事项

  • 操作前建议先备份数据,避免误操作导致数据丢失;
  • 如果你的表有主键或其他约束,需要确保删除操作不会违反约束;
  • 可以根据实际需求调整分组字段(比如是否只按code分组)或排序规则(比如保留id最大的行)。

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

火山引擎 最新活动