Как удалить старые повторяющиеся строки на основе 2 столбцов, но сохранить последнюю строку? - PullRequest
0 голосов
/ 16 июня 2019

Итак, у меня есть эта таблица (она называется 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 голосов
/ 16 июня 2019

Традиционный способ в 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;
0 голосов
/ 16 июня 2019

В MySQL 8.x (доступно с апреля 2018 года) вы можете использовать функции 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
)
...