查找重复的最低ID,并根据这些ID更新表

时间:2018-07-30 16:15:16

标签: sql duplicates sql-update sql-delete ssms-2017

问题

我有一个带有用于Hashtags的表的sql数据库,其中许多表的名称重复。

类似的语句

SELECT     *  
FROM       HashTag  
ORDER BY   Name

返回类似

的内容
Id   |  Name
1947 |  test
1950 |  sample
1962 |  test
1963 |  sample
1986 |  test
2014 |  example

我只想保留每个名称的ID最低的主题标签(“ test”为1947,“ sample”为1950),并使用此ID更新其他表,以替换较高的ID(例如:更新主题标签“ test” ;最低编号= 1947,较高编号= 1962,1986)。这些sql语句目前已手动更新,如下所示:

UPDATE             HashTaggedActivity
SET [HashTag_id]   = 1947
WHERE HashTag_id   in (1962, 1986)

Update             HashTaggedGroup
SET [HashTag_id]   = 1947
WHERE HashTag_id   in (1962, 1986)

DELETE             ht
FROM               HashTag ht
WHERE              ht.Id in (1962, 1986)

在此之后,我必须对HashTag'sample'执行此操作,这是一个容易出错且乏味的过程。 HashTag'example'不是重复的,不应导致更新其他表。

对于表HashTag中重复名称的每次出现,是否有任何方法可以编写一条sql语句?

到目前为止我尝试过的事情

我认为我必须结合一条语句才能获得ID所定的重复计数

select ht.Id, ht.Name, htc.dupeCount
from HashTag ht
inner join (
    SELECT ht.Name, COUNT(*) AS dupeCount
    FROM HashTag ht
    GROUP BY ht.Name
    HAVING COUNT(*) > 1
) htc on ht.Name = htc.Name
ORDER BY Id

给出

Id   |  Name    | dupeCount
1947 |  test    | 3
1950 |  sample  | 2
1962 |  test    | 3
1963 |  sample  | 2
1986 |  test    | 3
2014 |  example | 1

根据dupeCount使用我的UPDATE和DELETE语句,但是我不确定如何执行;-)

提前致以最诚挚的问候,

迈克尔

2 个答案:

答案 0 :(得分:0)

前两个update语句首先基于hashtag_id获得名称(最里面的选择),然后获取具有相同名称的hashtag中所有ID的最小值(下一步选择),然后相应地更新hashtag_id。 在这种情况下,它还将使用hashtag_id 1947和1950更新记录-但新值将与旧值相同。

update HashTaggedGroup
 set hashtag_id = 
    (select min(id) 
     from hashtag h1 
     where (
        select name 
        from hashtag h2 
        where h2.id=HashTaggedGroup.hashtag_id)=h1.name);


update HashTaggedActivity
 set hashtag_id = 
    (select min(id) 
     from hashtag h1 
     where (
        select name 
        from hashtag h2 
        where h2.id=HashTaggedActivity.hashtag_id)=h1.name);

以下删除操作适用于Mysql和SQLServer,可能需要对其他数据库进行调整(但是想法仍然相同)。如果确定来自hashtag的所有id都存在于HashTaggedActivity中,则可以简化查询。

delete h1 from hashtag as h1 
    inner join hashtag as h2 on 
              h1.name = h2.name and 
              h1.id > h2.id;

SQLFiddle for the above

答案 1 :(得分:0)

我将使用窗口功能:

with ht as (
      select ht.*, min(id) over (partition by name) as minid
      from hashtag ht
     )
update hta
    set hashtag_id = ht.minid
    from HashTaggedActivity hta join
         ht
         on hta.hashtag_id = ht.id
    where ht.minid <> hta.hashtag_id;

然后以类似的方式进行删除:

with ht as (
      select ht.*, min(id) over (partition by name) as minid
      from hashtag ht
     )
delete from ht
    where ht.minid <> id;