У меня есть таблица под названием 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.
Как я могу удалить повторяющиеся статусы, сохранив последние статусы? Любая помощь будет принята с благодарностью.
Какая у вас версия MySQL? Покажите нам результат SHOW CREATE TABLE tracking_history\G
.
@El_Vanja, спасибо. Все работает, как и ожидалось.
Образцы данных и желаемые результаты помогут. В реальном мире пакет может проходить через одни и те же статусы несколько раз, поэтому с этой проблемой нужно быть очень осторожным.
Вам нужно дополнительное условие корреляции в статусе:
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;
Можете попробовать с
AND t1.status = t2.status
? Убедились ли вы, что дубликаты больше не вводятся в базу данных?