MySQL,如何合并表中重复的条目。

8

可能是重复的问题:
如何删除重复行?
仅使用MySQL查询删除重复项?

我有一个大表,其中包含约14M个条目。表类型是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 条目,所以如果可能的话,我想避免循环。
欢迎任何评论!

可能这个问题的答案也对你有帮助:https://dev59.com/dXVD5IYBdhLWcg3wU56H - MBozic
你有任何ID或独特的东西吗?你能展示表的结构吗? - jcho360
3个回答

4

在你需要作为唯一的列上创建一个新的唯一键将自动清除表中的任何重复项。

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

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


谢谢,您的解决方案完美而且非常高效。 - sdespont
从MySQL 5.7.4开始,ALTER TABLE的IGNORE子句已被删除,使用它将会产生错误。 - viarnes

4

由于MySQL允许在update/delete语句中使用子查询,但如果它们引用要更新的表,则不允许使用。因此,我会先创建原始表的副本。然后:

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

但我可以想象复制一个有1400万条目的表可能需要一些时间...在复制时选择要保留的项目可能会使它更快:

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了,所以我相信肯定有更高性能的替代方案,但这应该可以工作;)


1

这是如何删除重复行的方法...我会给你写一个例子,你需要将其应用到你的代码中。我有一个演员表,其中包含ID,我想删除重复的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)

-现在我使用一个名为@a的变量来获取下一行的ID,如果它们具有相同的first_name(重复),则获取其ID,否则返回null。

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)

它可以运行,如果您有任何问题,请回信给我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接