Удалите повторяющиеся идентификаторы заказов, сохранив статус отслеживания - mysql

У меня есть таблица под названием tracking_history. В этой таблице будет храниться история отслеживания посылок. По некоторым причинам, когда когда-либо выполнялась функция checkTrackStatus, все существующие статусы отслеживания постоянно вставляются в таблицу. Вот последовательность статусов отслеживания. 'ACCEPTED','AT_SENDING_DEPOT','ON_THE_ROAD','AT_DELIVERY_DEPOT','DELIVERED' Я сохраняю идентификатор отслеживания, идентификатор заказа также в этой таблице. Поэтому мне нужно, чтобы для каждого идентификатора заказа был последний статус отслеживания ('ACCEPTED','AT_SENDING_DEPOT','ON_THE_ROAD','AT_DELIVERY_DEPOT','DELIVERED'), а оставшиеся повторяющиеся значения должны быть удалены. Я попытался с приведенным ниже запросом.

`DELETE t1 FROM tracking_history t1, tracking_history t2 
WHERE t1.id < t2.id AND t1.order_id = t2.order_id` 

Но этот запрос сохраняет только последние записи и удаляет все остальные. Means I am having all orders ids with DELIVERED Status only. Как я могу удалить повторяющиеся статусы, сохранив последние статусы? Любая помощь будет принята с благодарностью.

Можете попробовать с AND t1.status = t2.status? Убедились ли вы, что дубликаты больше не вводятся в базу данных?

El_Vanja 12.12.2020 10:41

Какая у вас версия MySQL? Покажите нам результат SHOW CREATE TABLE tracking_history\G.

Vérace 12.12.2020 10:44

@El_Vanja, спасибо. Все работает, как и ожидалось.

user3408779 12.12.2020 10:50

Образцы данных и желаемые результаты помогут. В реальном мире пакет может проходить через одни и те же статусы несколько раз, поэтому с этой проблемой нужно быть очень осторожным.

Gordon Linoff 12.12.2020 14:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
4
127
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно дополнительное условие корреляции в статусе:

DELETE t1 
FROM tracking_history t1
INNER JOIN tracking_history t2 
    ON  t1.id < t2.id 
    AND t1.order_id = t2.order_id
    AND t1.status = t2.status

Я бы рекомендовал дополнительно изменить запрос следующим образом:

DELETE t1 
FROM tracking_history t1
INNER JOIN (
    SELECT order_id, status, MAX(id) as id 
    FROM tracking_history 
    GROUP BY order_id, status
) t2 
    ON  t1.id < t2.id 
    AND t1.order_id = t2.order_id
    AND t1.status = t2.status

Преимущество этого подхода заключается в том, что каждая строка сопоставляется только один раз, в отличие от исходного запроса, который может попытаться удалить одну и ту же строку более одного раза. Следовательно, это более эффективно и в какой-то степени безопаснее.

Ответ принят как подходящий

Я хотел бы сохранить первый идентификатор при вставке строки, а не последний идентификатор. Это из-за другой информации, которая может быть полезной, особенно время вставки и кто сделал вставку. Для этой цели я бы оставил одну строку для каждого статуса, но сформулировал логику так:

delete th
    from tracking_history th join
         (select order_status, status, min(id) as min_id
          from tracking_history th2
          group by order_status, status
         ) th2
         using (order_status, status)
    where id > min_id;

Тем не менее, это все еще не кажется правильным. В конце концов, возможно, статус будет одинаковым для нескольких строк. Например, может быть несколько попыток переместить посылку со склада на адрес. Что вам действительно нужно, так это самый последний статус для каждой партии в tracking_history. Я не знаю, есть ли у вас какой-то «идентификатор партии». Но позвольте мне предположить, что есть что-то, возможно, дата входа, которая связывает все общие ценности воедино.

В этом случае вам понадобится последний статус для каждой «партии»:

delete th
    from tracking_history th join
         (select order_status, entry_date, max(id) as max_id
          from tracking_history th2
          group by order_status, entry_date
         ) th2
         using (order_status, entry_date)
    where id < min_id;

Другие вопросы по теме