【问题标题】:How to delete old duplicate rows based on 2 columns but keep the latest row?如何删除基于 2 列的旧重复行但保留最新行?
【发布时间】:2019-06-15 23:07:49
【问题描述】:

所以我有这张表(称为 test_table)

id  |  hotel_id  |  user_id
1   |  1         |  1
2   |  1         |  1
3   |  1         |  2
4   |  2         |  3
5   |  1         |  2
6   |  3         |  3

所以如果hotel_id和user_id相同,那么我想删除重复的行但保留最新的行(最新的行是id较高的行)。

所以删除我的表格后会如下表所示。

我删除了id 1,因为有一个更新的行id 2

我删除了id 3,因为有一个更新的行id 5

id  |  hotel_id  |  user_id
2   |  1         |  1
4   |  2         |  3
5   |  1         |  2
6   |  3         |  3

我尝试使用下面的代码,但它只检查一列是否重复。最有效的方法是什么?

delete test_table
   from test_table
  inner join (
     select max(id) as lastId, hotel_id
       from test_table
      group by hotel_id
     having count(*) > 1) duplic on duplic.hotel_id = test_table.hotel_id
  where test_table.id < duplic.lastId;

【问题讨论】:

  • 不要使用MAX(id)。改为使用ORDER BY。并且您可以使用LIMIT COUNT(*) - 1 留下一排
  • 此外,它仅基于一列找到它,因为您仅对一列进行分组。试试group by hotel_id, user_id
  • @Anthony 你是什么意思不要使用max(id) 你能给我举个例子吗?

标签: mysql sql database group-by sql-delete


【解决方案1】:

MySQL 中的传统方式使用JOIN

delete tt
    from test_table tt join
         (select tt.hotel_id, tt.user_id, max(tt.id) as max_id
          from test_table tt
          group by tt.hotel_id, tt.user_id
         ) tokeep
         on tokeep.hotel_id = tt.hotel_id and
            tokeep.user_id = tt.user_id and
            tokeep.max_id > tt.id;

如果id在表中是唯一的,则可以简化为:

delete tt
    from test_table tt left join
         (select tt.hotel_id, tt.user_id, max(tt.id) as max_id
          from test_table tt
          group by tt.hotel_id, tt.user_id
         ) tokeep
         on tt.id = tokeep.max_id
     where to_keep.max_id is null;

【讨论】:

    【解决方案2】:

    在 MySQL 8.x(自 2018 年 4 月起可用)中,您可以使用 windows 函数来识别 过时 行。例如:

    delete from test_table where id in (
      select id
      from (
        select
          id, row_number() over(partition by hotel_id, user_id order by id desc) as rn
        from test_table
      ) x
      where rn <> 1
    )
    

    【讨论】:

    • 您可能应该注意 8.x 的发布日期,因为我猜大多数堆栈还没有,所以这几乎是一个边缘功能。 (但一个伟大的,我很高兴有人提到它)
    • @Anthony 添加了发布日期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多