我正在删除mysql上的重复行并且只留下旧行(最少id),但我得到最大行错误
DELETE n1
FROM item_audit n1, item_audit n2
WHERE n1.id > n2.id AND n1.description = n2.description
答案 0 :(得分:0)
请注意,使用该连接条件,您将每行连接到之前的每个行(具有相同的描述)。这是子查询比连接更有效的情况之一。
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 *
包装器在子查询中使用删除目标。
或者,子查询上的连接可用于减少在幕后创建的中间结果集的大小。
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
;
如果失败,您可以将第一个id插入临时表,并且应该可以使用该表进行子查询。
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子句都可以放在最后,以完成增量删除。最后一个临时表版本的好处是每次增量删除后都不需要重新评估子查询(并且可以对临时表进行索引以加快速度)。