请注意,您显示的查询将删除两个重复项。我会假设你想保留一个或另一个。
这是我会怎么写这个查询:
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;
你还问有关测试。我建议你test
数据库复制包含重复的表行的一个示例:
CREATE TABLE test.table1test SELECT * FROM realdb.table1 LIMIT 10000;
现在,直到你满意的解决方案DELETE
是正确的,你可以对你的样本数据的实验。
USE test;
SET autocommit = 0;
DELETE ...
ROLLBACK;
我建议你命名你从头表中test
数据库的东西从你的真表的不同之处在你的真正的数据库。以防万一您在运行实验性的DELETE
时意外地仍在使用您的真实数据库作为默认数据库!
回复您的意见:
USE test
是mysql客户端内置的命令。它将test
数据库设置为默认数据库。当你在查询中命名表而不用数据库名限定它们时,这将成为默认数据库。请参见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
是值得的,因为它放弃了在该事务中所做的更改。这是一种快速返回到测试数据的初始状态的方法,以便您可以尝试其他实验。
DELETE t1
不是拼写错误。 DELETE
删除行,而不是整个表。 t1
是满足语句条件(尽管条件可能包括表中的每一行)的每个行的别名。见多表的描述删除在http://dev.mysql.com/doc/refman/5.1/en/delete.html
有点像当您运行PHP中的循环,并使用一个变量来遍历循环:for ($i=0; $i<100; ++$i)
...变量$i
呈现一系列的值,每个通过循环的时间有不同的价值。
下面演示了我的解决方案如何删除多个副本。我在test
数据库跑了这一点,我直接从我的命令窗口中粘贴的结果:
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)
我正要发送另一个示例查询,但是,你有没有测试过这个吗?在我看来,这两个记录将被删除。 – Fosco 2010-07-21 19:18:25
您可以用“选择”替换“删除”以测试您的查询。 – 2010-07-21 19:28:09