MySQL,如何合并表重复条目[重复]

Posted

技术标签:

【中文标题】MySQL,如何合并表重复条目[重复]【英文标题】:MySQL, how to merge table duplicates entries [duplicate] 【发布时间】:2012-09-25 12:17:54 【问题描述】:

可能重复:How can I remove duplicate rows?Remove duplicates using only a mysql query?

我有一个包含约 1400 万个条目的大表。表类型是 MyISAM 而不是 InnoDB。

不幸的是,我在此表中有一些重复的条目,我通过以下请求找到了这些条目:

SELECT device_serial, temp, tstamp, COUNT(*) c FROM up_logs GROUP BY device_serial, temp, tstamp HAVING c > 1

为避免将来出现这些重复,我想使用 SQL 请求将当前索引转换为唯一约束:

ALTER TABLE  up_logs DROP INDEX UK_UP_LOGS_TSTAMP_DEVICE_SERIAL,
ALTER TABLE up_logs ADD INDEX UK_UP_LOGS_TSTAMP_DEVICE_SERIAL (  `tstamp` ,  `device_serial` )

但在那之前,我需要清理我的重复项!

我的问题是:我怎样才能只保留一个重复条目?请记住,我的表包含 14M 条目,所以如果可能的话,我希望避免循环。

欢迎任何cmets!

【问题讨论】:

可能接受的关于这个问题的答案也会对你有所帮助:***.com/questions/18932/… 您有任何 ID 或独特的东西吗?你能展示一下表格的结构吗? 【参考方案1】:

在您需要作为唯一的列上创建一个新的唯一键将自动清除所有重复的表。

ALTER IGNORE TABLE `table_name`
    ADD UNIQUE KEY `key_name`(`column_1`,`column_2`);

IGNORE 部分不允许脚本在第一个错误发生后终止。并且默认行为是删除重复项。

【讨论】:

谢谢您,您的解决方案非常完美且非常高效 从 MySQL 5.7.4 开始,ALTER TABLE 的 IGNORE 子句被删除,使用它会产生错误。【参考方案2】:

由于 MySQL 允许在更新/删除语句中使用子查询,但如果它们引用您要更新的表,我会先创建原始表的副本。那么:

DELETE FROM original_table 
WHERE id NOT IN( 
    SELECT id FROM copy_table 
    GROUP BY column1, column2, ...
);

但我可以想象复制一个包含 14M 条目的表需要一些时间……在复制时选择要保留的项目可能会更快:

INSERT INTO copy_table 
    SELECT * FROM original_table 
    GROUP BY column1, column2, ...;

然后

DELETE FROM original_table 
WHERE id IN(
    SELECT id FROM copy_table
);

自从我上次使用 MySQL 和 SQL 以来已经有一段时间了,所以我很确定有一些性能更好的东西 - 但这应该可以工作 ;)

【讨论】:

【参考方案3】:

这是删除重复行的方法...我会写给你我的例子,你需要应用到你的代码。我有 ID 的 Actors 表,我想删除重复 first_name 的行

mysql> select actor_id, first_name from actor_2;
+----------+-------------+
| actor_id | first_name  |
+----------+-------------+
|        1 | PENELOPE    |
|        2 | NICK        |
|        3 | ED          |
....
|      199 | JULIA       |
|      200 | THORA       |
+----------+-------------+

200 rows in set (0.00 sec)

-现在,如果下一行具有相同的 first_name(重复,如果不是,则为 null),我使用名为 @a 的变量来获取 ID。

mysql> select if(first_name=@a,actor_id,null) as first_names,@a:=first_name from actor_2 order by first_name;
+---------------+----------------+
|  first_names  | @a:=first_name |
+---------------+----------------+
|          NULL | ADAM           |
|            71 | ADAM           |
|          NULL | AL             |
|          NULL | ALAN           |
|          NULL | ALBERT         |
|           125 | ALBERT         |
|          NULL | ALEC           |
|          NULL | ANGELA         |
|           144 | ANGELA         |
...
|          NULL | WILL           |
|          NULL | WILLIAM        |
|          NULL | WOODY          |
|            28 | WOODY          |
|          NULL | ZERO           |
+---------------+----------------+
200 rows in set (0.00 sec)

-现在我们只能得到重复的 ID:

    mysql> select first_names from (select if(first_name=@a,actor_id,null) as first_names,@a:=first_name from actor_2 order by first_name) as t1;
    +-------------+
    | first_names |
    +-------------+
    |        NULL |
    |          71 |
    |        NULL |
     ...
    |          28 |
    |        NULL |
    +-------------+
    200 rows in set (0.00 sec)

-最后一步,让我们删除!

mysql> delete from actor_2 where actor_id in (select first_names from (select if(first_name=@a,actor_id,null) as first_names,@a:=first_name from actor_2 order by first_name) as t1);
Query OK, 72 rows affected (0.01 sec)

-现在让我们检查一下我们的表格:

mysql> select count(*) from actor_2 group by first_name;
+----------+
| count(*) |
+----------+
|        1 |
|        1 |
|        1 |
...
|        1 |
+----------+
128 rows in set (0.00 sec)

它有效,如果您有任何问题给我回信

【讨论】:

以上是关于MySQL,如何合并表重复条目[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何避免没有主键和唯一键的重复条目?

MySQL 从具有重复引用条目的联合表中选择唯一记录

MySQL如何合并重复记录

如何在 MySQL 中查找重复条目 [重复]

如何将MYSQL数据库 2个同样的数据库合并在一起?

如何在MYSQL中联合多个表[重复]