【问题标题】:SQL - delete duplicate rowsSQL - 删除重复行
【发布时间】:2020-04-22 17:40:12
【问题描述】:

我正试图弄清楚如何从我的数据库中删除重复的行但保留一个:

|---------------------------|
| id   titleid     version  |
|---------------------------|
| 1   TEST1        1.60     | <--- keep
| 2   TEST1        1.60     | <--- delete
| 3   TEST1        1.60     | <--- delete
| 4   TEST1        1.60     | <--- delete
| 5   TEST55       1.55     | <--- not selected
| 6   TEST88       1.85     | <--- not selected
| 7   TEST56       1.60     | <--- keep
| 8   TEST56       1.60     | <--- delete
|---------------------------|

我已经能够弄清楚如何选择具有重复行的行:

SELECT a.*
FROM patch a
JOIN (
    SELECT titleid, version, COUNT(*)
    FROM patch
    GROUP BY titleid, version
    HAVING count(*) > 1
) b 
ON a.titleid = b.titleid
AND a.version = b.version 
ORDER BY a.version

如何修改此查询,使其删除重复的行,但保留一个?

我已经在 SO 和 Google 上寻找答案,但似乎没有一个能满足我的需求。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    这回答了问题的原始版本。

    这种情况下最简单的方法是清空表并重建它:

    create table temp_t as
        select distinct title_id, version
        from t;
    
    truncate table t;   -- back it up first!
    
    insert into t (title_id, version)
        select title_id, version
        from temp_t;
    

    另一种方法是添加一个自动递增的主键列,然后将其用于删除:

    alter table t add column id int auto_increment primary key;
    
    delete t
    from t left join
         (select title, version, min(id) as min_id
          from t
          group by title, version
         ) tt
         on t.id = tt.min_id
    where tt.min_id is null;
    
    alter table t drop column id;
    

    Here 是这个版本的数据库fiddle。

    【讨论】:

    • 感谢您的解决方案,戈登。是否可以进行不创建不同表/重建表的查询?
    • @AppelFlap 您的表中没有信息可以区分重复的单独记录。也许你已经简化了真实的结构,并且存在一些主索引?
    • @Akina 你的意思是如果有一个自动增量ID?如果是,我已经修改了我的问题以包含它。
    • @AppelFlap 任何主要或唯一索引 - 合成或自然。
    • @AppelFlap 。 . .(1) 我认为更改问题以使现有答案无效是不礼貌的。 (2) 提出的第二个解决方案与另一个答案基本相同,只是它显式添加了 id。
    【解决方案2】:

    对于titleidversion 的每个组合,您必须删除所有ids 不同于最小ids 的行:

    delete from patch
    where id not in (
      select t.id from (
        select min(id) id
        from patch
        group by titleid, version
      ) t  
    );
    

    请参阅demo
    结果:

    | id  | titleid | version |
    | --- | ------- | ------- |
    | 1   | TEST1   | 1.6     |
    | 5   | TEST55  | 1.55    |
    | 6   | TEST88  | 1.85    |
    | 7   | TEST56  | 1.6     |
    

    【讨论】:

      【解决方案3】:

      添加了主键 (`id`) - 所以

      DELETE t1.*
      FROM patch t1
      JOIN patch t2 USING (title, version)
      WHERE t1.id > t2.id 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-04
        • 2010-11-22
        • 2017-11-16
        • 1970-01-01
        • 2023-04-10
        • 2017-06-29
        • 2020-02-17
        • 2012-09-17
        相关资源
        最近更新 更多