如何在SQL Server中使用UPDATE和DELETE合并并删除重复行
在SQL Server中实现合并重复行并删除冗余数据的方案
嘿,这个需求我之前处理过类似的,咱们可以分更新合并和删除冗余两步来完成,下面是具体的操作方法和代码示例:
第一步:合并重复行的deviceType到保留行
首先,咱们需要把同一code、name、type分组下的所有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




