如何删除基于2列的旧重复行,但保留最新行?

时间:2019-06-15 23:07:49

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

所以我有这个表(称为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;

2 个答案:

答案 0 :(得分:0)

在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
)

答案 1 :(得分:0)

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;