Я удаляю повторяющиеся строки в mysql и оставляю только старую строку (наименьший id), но я получаю ошибку max row
DELETE n1
FROM item_audit n1, item_audit n2
WHERE n1.id > n2.id AND n1.description = n2.description
Имейте в виду, что с условием соединения вы соединяете каждую строку с каждой строкой перед ней (с тем же описанием). Это один из тех случаев, когда подзапрос будет намного эффективнее, чем объединение.
DELETE a
FROM item_audit a
WHERE (a.id, a.description) NOT IN
(SELECT * FROM
(
SELECT MIN(id), description
FROM item_audit
GROUP BY description
) AS realSubQ
)
На самом деле, если id уникален, он может быть даже проще:
DELETE a
FROM item_audit a
WHERE a.id NOT IN
(SELECT * FROM
( SELECT MIN(id)
FROM item_audit
GROUP BY description
) AS realSubQ
)
Как вы обнаружили, MySQL должен быть "обманут", чтобы использовать цель удаления в подзапросе с помощью дополнительной select *
wrapper.
В качестве альтернативы, объединение в подзапрос может быть использовано для уменьшения размера промежуточного результирующего набора, созданного за кулисами.
DELETE a
FROM item_audit a
LEFT JOIN (SELECT MIN(id) AS firstId FROM item_audit GROUP BY description) AS aFirst
ON a.id = aFirst.firstId
WHERE aFirst.firstId IS NULL
;
Если это не удается, вы можете вставить первый идентификатор в временную таблицу и иметь возможность сделать с ним подзапрос.
CREATE TEMPORARY TABLE 'old_ids'
SELECT MIN(ID) AS id
FROM item_audit
GROUP BY description;
DELETE a
FROM item_audit a
LEFT JOIN old_ids ON a.id = old_ids.id
WHERE old_ids.id IS NULL
;
В любом из этих случаев предложение LIMIT может быть помещено очень последним, чтобы выполнить инкрементное удаление. Последняя, временная таблица, версия имеет то преимущество, что подзапрос не будет нуждаться в повторной оценке после каждого инкрементного удаления (и временная таблица может быть проиндексирована для ускорения работы).