这是删除重复MySQL行的好方法吗?

我看到了创建具有唯一行的备用临时MySQL表的解决方案,但我不喜欢这个想法,因为我的表非常大并且移动它们会很麻烦(并且如果在期间会出现错误会产生巨大的问题移动).

但是,我确实找到了以下内容.你怎么看待这个(要检查的重复项是“field_name”)?

DELETE FROM table1
USING table1, table1 as vtable
WHERE (NOT table1.ID=vtable.ID)
AND (table1.field_name=vtable.field_name)

有人说这应该有用,但我不太确定.你怎么看?此外,索引根本会改变此命令的性能,例如,在“field_name”上有索引吗?

编辑:在运行之前有没有办法测试查询?据我所知,MySQL不支持DELETE查询的“解释”.

解决方法:

请注意,您显示的查询将删除两个重复项.我想你想要保留其中一个.

以下是我将如何编写此查询:

DELETE t1 FROM table1 AS t1 JOIN table1 AS t2 
  ON t1.id > t2.id AND t1.field_name = t2.field_name;

通过使用大于而不是非等于,您只删除一行(后一行),而不是两者.

(id,field_name)上的复合索引可能会有所帮助.您应该使用MySQL的EXPLAIN确认这一点以获得优化报告.但EXPLAIN只支持SELECT查询,因此您应该运行等效的SELECT来确认优化:

EXPLAIN SELECT * FROM table1 AS t1 JOIN table1 AS t2 
  ON t1.id > t2.id AND t1.field_name = t2.field_name;

你还询问了测试.我建议将包含重复项的行样本复制到测试数据库中的表:

CREATE TABLE test.table1test SELECT * FROM realdb.table1 LIMIT 10000;

现在,您可以对样本数据执行实验,直到您对DELETE解决方案的准确性感到满意为止.

USE test;
SET autocommit = 0;
DELETE ... 
ROLLBACK;

我建议在测试数据库中命名您的临时表,这与您真实数据库中的真实表格不同.以防您在意外使用真实数据库作为默认数据库时运行实验性DELETE!

你的意见:

USE测试是一个mysql客户端内置命令.它将测试数据库设置为默认数据库.当您在查询中为表命名而不用数据库名称限定表时,这将是默认数据库.见http://dev.mysql.com/doc/refman/5.1/en/use.html

SET autocommit = 0关闭隐式提交每个查询的事务的默认行为.因此,您必须显式提供COMMIT或ROLLBACK命令才能完成事务.见http://dev.mysql.com/doc/refman/5.1/en/commit.html

在进行实验时使用ROLLBACK是值得的,因为它会丢弃在该事务中所做的更改.这是一种快速返回测试数据初始状态的方法,因此您可以尝试其他实验.

删除t1不是拼写错误. DELETE删除行,而不是整个表. t1是满足语句条件的每一行的别名(尽管条件可能包括表中的每一行).请参阅http://dev.mysql.com/doc/refman/5.1/en/delete.html处的多表删除说明

类似于在PHP中运行循环并使用变量迭代循环时:for($i = 0; $i< 100; $i)...变量$i采用一系列值,每次通过循环它都有不同的值. 这是一个演示,展示了我的解决方案如何删除多个重复项.我在我的测试数据库中运行它,我直接从命令窗口粘贴结果:

mysql> create table table1 (id serial primary key, field_name varchar(10));
Query OK, 0 rows affected (0.45 sec)

mysql> insert into table1 (field_name) 
       values (42), (42), (42), (42), (42), (42);
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> select * from table1;
+----+------------+
| id | field_name |
+----+------------+
|  1 | 42         | 
|  2 | 42         | 
|  3 | 42         | 
|  4 | 42         | 
|  5 | 42         | 
|  6 | 42         | 
+----+------------+
6 rows in set (0.00 sec)

mysql> delete t1 from table1 t1 join table1 t2 
       on t1.id > t2.id and t1.field_name = t2.field_name;
Query OK, 5 rows affected (0.00 sec)

mysql> select * from table1;
+----+------------+
| id | field_name |
+----+------------+
|  1 | 42         | 
+----+------------+
1 row in set (0.00 sec)
上一篇:java – 删除ArrayList中的重复元素,并在第一个元素后面的括号中添加总出现次数


下一篇:MySQL通过UPDATE / DELETE整合重复的数据记录