SQL удаляет повторяющиеся строки на основе нескольких полей - PullRequest
1 голос
/ 15 октября 2019

У меня есть следующая таблица в sql:

id | trip_id | stop_id | departure_time
----------------------------------------
1  |        1|        1|        06:25:00
2  |        1|        2|        06:35:00
3  |        1|        3|        06:45:00
4  |        1|        2|        06:55:00

Что мне нужно сделать, это определить, где trip_id, как несколько экземпляров определенного stop_id (в данном случае stop_id 2).

Затем мне нужно удалить любые дубликаты, оставив только ту, которая имеет самое позднее время отправления.

Таким образом, с учетом приведенной выше таблицы Id удалите строку с идентификатором 2 и оставьте:

id | trip_id | stop_id | departure_time
----------------------------------------
1  |        1|        1|        06:25:00
3  |        1|        3|        06:45:00
4  |        1|        2|        06:55:00

Мне удалось сделать это с помощью серии SQL-запросов, но я столкнулся с проблемой N + 1, и это заняло целую вечность.

Кто-нибудь может порекомендовать, как я могу сделать это в одном запросе? Или, по крайней мере, идентифицировать все идентификаторы строк, которые нужно удалить в одном запросе?

Я делаю это в ruby ​​на рельсах, поэтому, если вы предпочитаете решение для активной записи, я бы не стал вас ненавидеть за это:)

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 15 октября 2019

Вы можете использовать следующую логику:

DELETE
FROM yourTable t1
WHERE EXISTS (SELECT 1 FROM yourTable t2
              WHERE t2.trip_id = t1.trip_id AND
                    t2.stop_id = t1.stop_id AND
                    t2.departure_time > t1.departure_time);

На простом английском языке это означает, что нужно отсканировать всю таблицу и удалить любую запись, для которой мы можем найти другую запись с идентичными trip_id и stop_id, где время отправления также больше , чем время записи, рассматриваемой для удаления. Если мы найдем такое совпадение, то оно будет дубликатом в соответствии с вашим определением.

0 голосов
/ 15 октября 2019

попробуйте, как показано ниже

DELETE FROM table a
WHERE a.ctid <> (SELECT max(b.ctid)
                 FROM   table b
                 WHERE  a.stop_id = b.stop_id)
0 голосов
/ 15 октября 2019

Вы можете попробовать ниже путь -

   DELETE FROM tablename
   WHERE id in
    (
    select id from
      (select *, row_number() over(partition by stop_id order by departure_time desc) as rn from tablename)aa
    )A where rn>1
...