我看到了创建具有唯一行的备用临时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)