我有一个大的MySql表,我需要从中删除重复项 - 要符合重复条件,一行与两列上的另一行匹配:
SELECT * FROM JwDistanceSurnames n1, JwDistanceSurnames n2
WHERE n1.JwDistanceSurnameId > n2.JwDistanceSurnameId
AND n1.Surname1 = n2.Surname1
AND n1.Surname2 = n2.Surname2
LIMIT 1000;
因为它是一张大桌子,所以我想分批进行。我的理解是我应该能够使用LIMIT来实现这一目标。但是,这不会执行,引用语法错误:
DELETE n1 FROM JwDistanceSurnames n1, JwDistanceSurnames n2
WHERE n1.JwDistanceSurnameId > n2.JwDistanceSurnameId
AND n1.Surname1 = n2.Surname1
AND n1.Surname2 = n2.Surname2
LIMIT 1000;
错误是什么?是不是可以使用这种简单的方法进行批处理?
MCVE:
CREATE TABLE `JwDistanceSurnames` (
`JwDistanceSurnameId` int(11) NOT NULL AUTO_INCREMENT,
`Surname1` varchar(999) DEFAULT NULL,
`Surname2` varchar(999) DEFAULT NULL,
`JwScore` double NOT NULL,
PRIMARY KEY (`JwDistanceSurnameId`),
KEY `Surname1` (`Surname1`),
KEY `Surname2` (`Surname2`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO `JwDistanceSurnames`
(`JwDistanceSurnameId`, `Surname1`, `Surname2`, `JwScore`)
VALUES (null,'williamsom' ,'williamson' ,0.959999999999998);
重复插入几次。然后运行删除。预期输出是单行,具有给定值。保留哪一行并不重要。
错误是:
错误代码:1064。您的SQL语法有错误;检查 手册,对应右边的MySQL服务器版本 使用的语法靠近  ORDER BY n1.JwDistanceSurnameId LIMIT 1000'在 第5行
答案 0 :(得分:2)
从this SO question开始,当引用多个表时,LIMIT
语句似乎无法使用DELETE
。解决此问题的一个技巧是在子查询中使用LIMIT
来标识要删除的记录,然后再联接回目标表:
DELETE t1
FROM JwDistanceSurnames t1
INNER JOIN
(
SELECT n1.JwDistanceSurnameId
FROM JwDistanceSurnames n1
INNER JOIN JwDistanceSurnames n2
ON n1.JwDistanceSurnameId > n2.JwDistanceSurnameId
WHERE n1.Surname1 = n2.Surname1 AND n1.Surname2 = n2.Surname2
ORDER BY <some_column> -- IMPORTANT! without this you may get random records
LIMIT 1000
) t2
ON t1.JwDistanceSurnameId = t2.JwDistanceSurnameId;
因此,标记为t2
的子查询使用LIMIT
一次识别1000个记录的批次以进行删除,然后我们使用另一个连接来实际标记这些目标记录。
另请注意,在没有LIMIT
的情况下使用ORDER BY
并不是一个定义明确的事情,因为SQL表是在无序的记录集上建模的。如果您有一些业务逻辑确定应删除批次的顺序,那么请考虑添加ORDER BY
子句(除非它真的无关紧要,这对我来说似乎不太重要)。