如何使用 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 中使用 UPDATE
和 DELETE
语句执行此操作?
非常感谢任何帮助!
【问题讨论】:
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 中的重复行?的主要内容,如果未能解决你的问题,请参考以下文章