Delete all Duplicate Rows except for One in MySQL?
Possible Duplicate:
Remove duplicate rows in MySQL
如何从MySQL表中删除所有重复数据?
例如,使用以下数据:
1 2 3 4 5 6 7 8 9 10 11 12
| SELECT * FROM names ;
+----+--------+
| id | name |
+----+--------+
| 1 | google |
| 2 | yahoo |
| 3 | msn |
| 4 | google |
| 5 | google |
| 6 | yahoo |
+----+--------+ |
如果是SELECT查询,我会使用SELECT DISTINCT name FROM names;。
如何使用DELETE执行此操作以仅删除重复项并仅保留每条记录的一条记录?
-
stackoverflow.com/questions/3311903/&hellip重复; 和stackoverflow.com/questions/2867530/… (讽刺地。)
-
这不是一个完全重复的问题,因为这特别要求DELETE命令执行相同的操作,以便需要添加唯一索引的ALTER命令让MySQL自动删除重复的行。 在这种情况下,我们正在选择我们想要删除重复项的确切方式。
-
所以关于重复的问题有重复吗?嗯
Editor warning: This solution is computationally inefficient and may bring down your connection for a large table.
注意 - 您需要先在桌子的测试副本上执行此操作!
当我这样做时,我发现除非我还包括AND n1.id <> n2.id,否则它会删除表格中的每一行。
如果要保留具有最低id值的行:
如果要保留具有最高id值的行:
我在MySQL 5.1中使用了这种方法
不确定其他版本。
更新:由于人们谷歌搜索删除重复项最终在这里
虽然OP的问题是DELETE,但请注意,使用INSERT和DISTINCT要快得多。对于具有800万行的数据库,以下查询花了13分钟,而使用DELETE,花费了超过2小时但尚未完成。
-
优秀的解决方它工作得很好。但我有一个建议,我们应该交换条件。而不是[WHERE n1.id> n2.id AND n1.name = n2.name]我们应该写[WHERE n1.name = n2.name AND n1.id> n2.id]如果我们有这么多,它将提高性能数据。
-
仅供参考:这会忽略列"name"为空的行。
-
sqlfiddle.com/#!2/e5df9用于架构示例。可能需要加载你的MySQL实例。然后执行:SELECT * FROM deldup;删除n1 FROM deldup n1,deldup n2 WHERE n1.or_id
-
@ user307635我认为mysql优化器会处理正确的顺序吗?
-
当我尝试用SELECT替换DELETE时,我得到一个unknown column n1 in field list?这只适用于DELETE吗? (mysql 5.5)
-
@Peterdk DELETE采用表名(如果指定多个表则需要),SELECT采用列名,或尝试"SELECT * ..."。
-
这个答案中的NB是非常重要的孩子。但这是一个优秀的MySQL。请注意,对于可能重复多次重复的表,您还需要一个GROUP BY n1.id子句。
-
我喜欢这个解决方案,但你有建议在更大的桌子上进行优化吗?
-
那么这对大表有什么用呢?我有400k +行。它适用于上面给出的sqlfiddle。
-
小心! MySQL的=符号不区分大小写。这将删除Test Name,因为它将匹配Test Name。
-
n1代表什么?这是专栏吗?
-
@mmr n1是表别名(... FROM names n1)
-
谢谢!当ALTER IGNORE TABLE table ADD UNIQUE INDEX index1(table.column_name)不起作用时,这非常有效
-
不知怎的,它没有用,对我来说它删除了所有重复的值。以下查询工作正常。
-
老兄,带着"n.b."就像你应该把它放在其他一切之前!
-
如果n1.id和n2.id也可能重复,会发生什么?
-
这在10,000个记录表上花了171秒,重复450个。 OMG小马的回答耗时4秒。
-
毫无疑问,它是最优雅和最优秀的解决方案......节省了我的时间:)
-
我每隔几天运行一次......想着写一个小脚本来通过cron来做这件事。感谢一百万这个简单的解决方案......我能不止一个upvote选项
-
此查询不适用于MySQL版本:5.5.47-0ubuntu0.14.04.1
-
在mysql 5.7(centos)上,这似乎不能正常工作
-
DISTINCT解决方案很棒,但要小心。如果您只有两个列,一个ID和一个名称,您可以按名称压缩行 - 但是如果您有其他具有不同值的字段(您可以容忍丢失一个或多个重复项)会怎么样?在这种情况下,由于额外的字段,DISTINCT将无法工作。在这种情况下,使用INSERT INTO tmp SELECT .. GROUP BY..。另外,请注意重命名序列和innoDB外键引用!!并确保您不会丢失任何索引。所有好东西都要检查。
-
OH,在上面的方法中,如果你想选择第一个,则使用MIN(id),如果你想选择最后一个,则使用MAX(id)。
-
谢谢你!
-
谢谢。有150k的记录花了3s!
-
如果有人有兴趣,请在这里(stackoverflow.com/questions/3311903/…)我解释如何使用临时表以可靠和快速的方式删除MySQL重复项(使用不同用例的示例)。
-
大!但是,有没有更快的解决方案?例如,对于具有2百万条记录的表格。
-
这不应该是选择答案。我的表上有非常短的数据,有100,000行,而你的查询使我的服务器关闭了mysql太多的连接错误。我等了10分钟才看到结果,但没有。我最终停止了查询并重新启动我的mysql服务器以恢复我的服务器。
-
@ user198989 - 同意; OMG Ponies的答案在大型桌子上本质上更快。如果每条记录有多个重复项,则尤其如此。
如果要保留具有最低id值的行:
如果您想要最高的id值:
子查询中的子查询对于MySQL是必需的,否则您将收到1093错误。
-
'x'做什么?
-
@GDmac它充当内部查询的别名。如果未指定,则将引发错误。
-
这是一个更好的解决方案。 masa-255的那个不起作用。什么是x?
-
@wbinky它充当内部查询的别名。如果未指定,则将引发错误。
-
但x是什么? (开玩笑)
-
看来这个sql也删除了独特的行。所有行
-
如果我有相同的身份怎么办?
-
如果你有大数据,这是一个比masa-255更好的解决方案。谢谢。
-
其实就像使用临时表一样
-
@GDmac:每个派生表都需要别名。 x在此处用作从自定义查询派生的表的别名。
-
@Asmita你可以使用DELETE FROM NAMES WHERE id NOT IN (SELECT * FROM (SELECT MAX(n.id) FROM NAMES n GROUP BY n.id) x)
-
执行时间很长
-
@Matt''Brien"为什么男模特买?"
-
这是为数不多的实际工作之一
-
x可以写为AS x或AS temp或AS `temp`,以使其更清晰,它是外部选择生成的表的随机别名。 MySQL不允许您对动作(DELETE,UPDATE)和条件使用相同的表,因此将条件包装在另一个SELECT中允许创建临时表并给出别名。
-
先生,我希望能得到越来越多的回报
-
对于具有500K记录的表,仅花费8秒钟。谢谢。
-
与接受的答案相比,这是超快的!
-
谢谢你,先生!