0

问题

我有一个带有 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(例如:更新主题标签“测试”;最低 ID = 1947,更高的 ID = 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 语句,但我不确定如何执行此操作 ;-)

在此先感谢并致以最诚挚的问候,

迈克尔

4

2 回答 2

0

前两个更新语句首先根据 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,它可能需要对其他 DB 进行调整(但想法保持不变)。如果您确定 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

于 2018-07-30T16:46:55.393 回答
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;
于 2018-07-30T17:14:24.687 回答