如何使用 UPDATE 合并和删除 SQL 中的重复行?

Posted

技术标签:

【中文标题】如何使用 UPDATE 合并和删除 SQL 中的重复行?【英文标题】:How do I merge and delete duplicated rows in SQL using UPDATE? 【发布时间】:2021-04-07 01:49:56 【问题描述】:

例如,我有一个表格:

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

我希望结果是:

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

如何在 SQL Server 中使用 UPDATEDELETE 语句执行此操作?

非常感谢任何帮助!

【问题讨论】:

ID 列是否唯一?并且您确定要连接设备类型而不是每个记录吗?这通常是一种不好的做法,所以我想我会在做任何事情之前先问清楚。 您还想“重新编号”所有其他未受影响行的 ID 值吗?您需要重新考虑您的餐桌设计。 【参考方案1】:

我实际上可能建议保持原始数据不变,而是在此处创建一个视图:

CREATE VIEW yourView AS
SELECT ROW_NUMBER() OVER (ORDER BY MIN(id)) AS id,
       code, name, type,
       STRING_AGG(deviceType, '&') WITHIN GROUP (ORDER BY id) AS deviceType
FROM yourTable
GROUP BY code, name, type;

Demo

实际进行更新的一个主要原因是每次新数据进入时,您可能必须一遍又一遍地运行该更新。相反,只保留原始数据并偶尔运行视图可能会在这里表现更好。

请注意,我假设您使用的是 SQL Server 2017 或更高版本。如果不是,那么 STRING_AGG 将不得不被替换为更丑陋的方法,但在这种情况下您应该考虑升级。

【讨论】:

GROUP_CONCAT 不是 T-SQL 函数。 普通记录的Id不同。 尽管我打算回答这个问题,提出一些不同的建议,但我认为这是一个更好的方法。我正在等待 OP 的回复,因为意图可能是需要的。但实际上,这将是 IMO 的最佳方法。 感谢您的解决方案和解释,它确实帮助我打开了思路。我会注意的! +1【参考方案2】:

要做你想做的事,你需要两个单独的语句。

这会使用组中的所有设备类型更新每个组的“第一”行:

update t
set t.devicetype = t1.devicetype
from mytable t
inner join (
    select min(id) as id, string_agg(devicetype, '&') within group(order by id) as devicetype
    from mytable
    group by code, name, type
    having count(*) > 1
) t1 on t1.id = t.id

这会删除除每组第一行之外的所有内容:

with t as (
    select row_number() over(partition by code, name, type order by id) rn
    from mytable
) 
delete from t where rn > 1

Demo on DB Fiddle

【讨论】:

...并且删除和更新都必须包装在一个事务中,特别是如果要从外部调用应用程序执行此代码。 @TimBiegeleisen 的答案和这个答案一样有效,我正在关注这个答案,因为这正是我所要求的,我只是在自己测试一些实验,谢谢你们这么多。 +1

以上是关于如何使用 UPDATE 合并和删除 SQL 中的重复行?的主要内容,如果未能解决你的问题,请参考以下文章

SQL DML数据操作语言 教程

SQL插入,使用合并存储过程更新

SQL Server 2005中的分区表:删除(合并)一个分区

DB2 中的合并查询

SQL基本语法

删除所有空格并将多行合并为 SQL 中的单行