从MySQL数据库中删除重复的条目

时间:2011-03-17 05:51:14

标签: php mysql

我有一个包含8列的表格,但随着时间的推移,我已经收集了大量的重复数据。我用类似的话题看了另一个问题,但它没有解决我目前遇到的问题。

+---------------------------------------------------------------------------------------+
| id | market | agent | report_name | producer_code | report_date | entered_date | sync |
+---------------------------------------------------------------------------------------+

定义唯一条目的内容基于market,agent,report_name,producer_code和report_date字段。我正在寻找的是列出所有重复条目并删除它们的方法。或者只是删除重复的条目。

我已经考虑过使用脚本来完成它,但是该表包含2.5mil的条目,并且它将花费的时间是不可行的。

有人可以提出任何替代方案吗?我看到人们使用以下查询获得重复列表,但不确定如何使其适应我的情况:

SELECT id, count(*) AS n
 FROM table_name
GROUP BY id
HAVING n > 1

4 个答案:

答案 0 :(得分:6)

您可以考虑以下两种策略。您必须根据实际认为重复的内容调整用于选择重复项的列。我刚刚列出了除id列之外的所有列出的列。

第一个只创建一个没有重复的新表。有时这实际上比尝试删除所有违规行更快更容易。只需创建一个新表,插入唯一的行(我使用min(id)作为结果行的id),重命名这两个表,并且(一旦你满意一切正常工作)删除原始表。当然,如果你有任何外键约束,你也必须处理它们。

create table table_copy like table_name;

insert into table_copy
(id, market, agent, report_name, producer_code, report_date, entered_date, sync)
select min(id), market, agent, report_name, producer_code, report_date, 
       entered_date, sync
from table_name
group by market, agent, report_name, producer_code, report_date, 
         entered_date, sync;

RENAME TABLE table_name TO table_old, table_copy TO table_name;

drop table table_old;

第二个策略只删除重复项,使用临时表来保存有关哪些行具有重复项的信息,因为MySQL不允许您从子查询中删除的同一个表中进行选择。只需创建一个临时表,其中包含标识重复项的列以及实际保存要保留的id的id列,然后您可以执行多表删除,您可以在其中连接两个表以仅选择重复项。

create temporary table dups
select min(id), market, agent, report_name, producer_code, report_date, 
       entered_date, sync
from table_name
group by market, agent, report_name, producer_code, report_date, 
         entered_date, sync
having count(*) > 1;

delete t 
from table_name t, dups d
where t.id != d.id
and t.market = d.market
and t.agent = d.agent
and t.report_name = d.report_name
and t.producer_code = d.producer_code
and t.report_date = d.report_date
and t.entered_date = d.entered_date
and t.sync = d.sync;

答案 1 :(得分:1)

您可以根据“关键”字段找到欺骗行为:

select id, count(*) as row_count
from table
group by market, agent, report_name, producer_code, report_date
having (row_count > 1)

然后您可以在删除脚本中使用它。当然,你必须非常小心这样做,因为它会返回所有重复的行,并且你想要从每个分组中保存至少一行。

答案 2 :(得分:1)

另一个简单的方法是

  1. 创建新表
  2. 在您需要唯一的字段上放置一个UNIQUE索引(主键是一种特殊的唯一索引)
  3. 使用INSERT IGNORE INTO newtable SELECT * FROM oldtable(ORDER BY,如果你想保留最后/第一条记录 - 如果其他列有差别的话)
  4. 删除旧表并将新表重新命名为旧表

答案 3 :(得分:0)

您还可以在唯一条目所基于的列上使用主键,这将阻止添加具有重复详细信息的新记录。