您当前的位置:首页 > 电脑百科 > 数据库 > MYSQL

MySQL如何删除重复数据

时间:2021-01-13 10:23:20  来源:  作者:

MySQL中经常会遇到重复的数据,那么当我们遇到重复的时候的时候,如果定位哪些数据是有重复的记录?如何删除重复的数据?我们该怎么做呢?接下来我们一步步来分析一下遇到这样的情况后,该如何处理。

MySQL如何删除重复数据

咋办呢?

初始化实验环境

我们创建一个简单的表user_info,然后基于这个表进行分析重复数据的处理情况。其中的id为自增主键,name、sex、age三个列是我们判断是否为重复数据的key,如果这三列的值相同,则认为这行数据为重复数据。

  • 建表语句如下:
CREATE TABLE `user_info` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `sex` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `remark` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
  • 初始化数据如下:
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (1, 'A', '男', 22, '第一个A');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (2, 'B', '女', 33, '第一个B');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (3, 'C', '男', 44, '第一个C');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (4, 'D', '女', 55, '第一个D');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (5, 'A', '男', 22, '第二个A');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (6, 'B', '女', 33, '第二个B');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (7, 'C', '男', 44, '第二个C');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (8, 'D', '女', 55, '第二个D');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (9, 'E', '男', 18, '第一个E');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (10, 'A', '男', 22, '第三个A');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (11, 'B', '女', 33, '第三个B');
INSERT INTO `tmp_test`.`user_info`(`id`, `name`, `sex`, `age`, `remark`) VALUES (12, 'F', '男', 15, '第一个F');
  • 最后表中数据如下:
MySQL如何删除重复数据

初始化的测试数据

明确需求

假设我们的要求是保留重复数据中,第一次出现的数据,后面出现的数据不保留。

也就是我们的上面的这个表中每一组重复数据中id最小的一行数据需要保留,其他比较大的id的重复的数据行需要被删除。当然如果是要保留id行最大的一行数据最为最后的数据行也是可以了,只要在查询的时候,稍微修改一下SQL语句的min(id)或max(id)函数即可。

MySQL如何删除重复数据

开整

查找重复的数据

基于前面我们初始化的实验数据,首先我们要查询出那些数据是有重复数据的行,通过下面的SQL语句,可以得到结果:其中有重复数据的是name值为A、B、C、D的四种类型的数据。

  • 使用如下SQL可以查询出来那些数据行有重复记录,并统计出重新出现的次数。
select 
	name, sex, age, 
  count(*) as count -- 数据重复出现的次数
from user_info 
group by name, sex, age 
having count(*) > 1;
  • 重复数据在表中的统计结果如下:
MySQL如何删除重复数据

数据重复的统计情况

查找要保留的数据

上面我们知道该如何查询哪些数据是重复数据了,那么我们需要保留的数据是哪些?

  • 使用下面的SQL既可以获取到我们要保留的数据行:
select * from user_info 
where id in (
	select 
		min(id) 
	from user_info 
	group by name, sex, age
);
  • 结果如下:
MySQL如何删除重复数据

每组重复数据中,id值最小的数据行

上面的结果就是我们需要最后留下来的数据。这里包含了非重复的时候和每一组重复的数据中id最小的数据行。

删除重复的数据

方法一

这是最笨的一种方式,也是最容易理解的一种方式,效率也比较低。思路如下:

MySQL如何删除重复数据

步骤一


MySQL如何删除重复数据

步骤二


MySQL如何删除重复数据

步骤三

从上面的过程中,我们一步一步定位到了我们需要删除的数据是哪些。定位到这些数据之后,删除的时候,只要把查询语句改为删除语句即可。所以最后通过这样的方式来删除我时候,我们的删除语句如下:

delete from user_info 
where (name,sex,age) in ( 
	select x.* from ( -- 删除的时候,这里要在包裹一层子查询
		select -- 查询重复数据中,name, sex, age的值
			name, sex, age
		from user_info
		group by name, sex, age
		having count(*) > 1
	) as x
)
and id not in (
	select min_id from ( -- 删除的时候,这里要在包裹一层子查询
		select -- 查询重复数据中,最小的id值
			min(id) as min_id
		from user_info 
		group by name, sex, age
		having count(*) > 1
	) as y
);

注意:上面的删除语句中,我们在两个where条件中的子查询语句外面又包裹了一层子查询,即为上面SQL语句中的as x和as y两个查询语句,之所以包裹一层的原因是在程序如下的错误提示:

1093 - You can't specify target table 'user_info' 
for update in FROM clause, Time: 0.084000s

上述错误的原因是:修改一个表的时候子查询不能是这被修改的这个表,所以,我们的解决办法是,在子查询外面再套一层查询语句就可以了。

方法二

上面方法一的思路是想办法找到我们要删除的数据是哪些,然后我们在删除的时候,使用where条件去匹配这些查询出来要删除的数据行,以此来达到删除重复数据的目的。

MySQL如何删除重复数据

换个思路解决

此时,我们不妨换一个角度思考:我们不要去关注哪些是我们需要删除的重复数据,相反,我们去关注哪些是我们需要留下来的数据。然后我们可以在删除的时候,使用取反的方式not in我们需要保留下来的数据,那不是就我们需要删除的数据吗?

所以,我们想一想哪些使我们需要留下来的数据呢?每一组数据中,id值最小的哪一行就是我们要保留的数据行。其余的我们就不关心了。那么怎么样才能取到这样的数据行呢?

  • 使用下面的SQL语句可以获取我们需要保留的数据行的所有的id的值:
select 
	min(id) 
from user_info 
group by name, sex, age;
  • 结果如下:
MySQL如何删除重复数据

 

既然我们想要保留的数据行的id集合得到了,在我们要删除数据的where条件中,使用not in我们要保留的id集合,不就是需要删除的数据吗?

  • 删除重复数据的语句如下:
delete from user_info 
where id not in(
	select min_id from (
		select 
			min(id) as min_id
		from user_info 
		group by name, sex, age
	) as x
);

注意:这里为了避免MySQL的1903错误,我们也在where条件的子查询中包裹了另外一个子查询,即上面SQL中as x查询语句。

方法三

MySQL如何删除重复数据

寻找更高效简单的方法

通过两个表关联的方式来删除数据,这个方式效率比较高,推荐使用这种方式。自己和自己关联,关联的条件就是我们判断数据是否为重复数据的key。除此之外,最重要的一个条件是:两个表的id关联条件,这个是删除保留数据的关键条件。

  • 查询重复数据的SQL语句如下:
select a.*,b.* 
from user_info as a 
inner join user_info as b 
on a.name = b.name 
and a.sex = b.sex 
and a.age = b.age
and  a.id > b.id;
  • 结果如下:
MySQL如何删除重复数据

 

写法1

删除重复数据SQL语句如下:

delete a.*
from user_info as a 
inner join user_info as b 
on a.name = b.name 
and a.sex = b.sex 
and a.age = b.age
and  a.id > b.id;

写法2

除了上面的那种写法之外,还有另外一种写法,如下:

查询待删除的重复数据SQL如下:

select * from user_info as a 
where a.id <> (
	select 
		min(b.id) 
	from user_info as b 
	where a.name = b.name
	and a.sex = b.sex
	and a.age = b.age
);

删除重复数据的SQL语句如下:

delete a.* from user_info as a
where a.id <> (
	select
		min(b.id)
	from (
		select * from user_info
	) as b
	where a.`name`= b.`name`
	and a.sex = b.sex
	and a.age = b.age
);

总结

以上是对于MySQL中重复数据删除的时候,经常使用的方法。对于其他数据库中存在的重复数据,删除的思路也是这些,只是具体到SQL语句的写法可能稍有稍有差异。只要你掌握了思路,具体到SQL语句的写法,尝试几次就可以成功。

MySQL如何删除重复数据

 

以上,希望能帮助到你。

最后提醒一点: 在真正删除之前,记得对原数据备份一下。以便删除错误后,数据不能恢复回来。可以使用如下的语句来创建一个备份表,以便于在删除错误后,把数据恢复到原来的表中去。

create table user_info_bak as select * from user_info; --创建一个备份表
truncate table user_info; -- 清空原始表中的数据
insert into user_info select * from user_info_bak; -- 从备份表中把数据插入到原始表中

像上面这样操作,数据如果删除失误的时候,可以从user_info_bak中还原数据到user_info表中。



Tags:MySQL   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
作者:雷文霆 爱可生华东交付服务部 DBA 成员,主要负责Mysql故障处理及相关技术支持。爱好看书,电影。座右铭,每一个不曾起舞的日子,都是对生命的辜负。 本文来源:原创投稿 *爱可生...【详细内容】
2021-12-24  Tags: MySQL  点击:(6)  评论:(0)  加入收藏
一、为什么要搭建主从架构呢1.数据安全,可以进行数据的备份。2.读写分离,大部分的业务系统来说都是读数据多,写数据少,当访问压力过大时,可以把读请求给到从服务器。从而缓解数据...【详细内容】
2021-12-15  Tags: MySQL  点击:(10)  评论:(0)  加入收藏
生成间隙(gap)锁、临键(next-key)锁的前提条件 是在 RR 隔离级别下。有关Mysql记录锁、间隙(gap)锁、临键锁(next-key)锁的一些理论知识之前有写过,详细内容可以看这篇文章...【详细内容】
2021-12-14  Tags: MySQL  点击:(17)  评论:(0)  加入收藏
binlog 基本认识 MySQL的二进制日志可以说是MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二...【详细内容】
2021-12-14  Tags: MySQL  点击:(13)  评论:(0)  加入收藏
为查询优化你的查询 大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查...【详细内容】
2021-12-09  Tags: MySQL  点击:(15)  评论:(0)  加入收藏
测试的目的和原因,公司有很多程序员,每个程序员对数据库和表结构都有自己的理解。而且每个程序员的理解往往是以效率考虑。既然都是为了效率考虑,那么我就来测试一下究竟哪种使...【详细内容】
2021-12-08  Tags: MySQL  点击:(14)  评论:(0)  加入收藏
当你们考虑项目并发的时候,我在部署环境,当你们在纠结使用ArrayList还是LinkedArrayList的时候,我还是在部署环境。所以啊,技术不止境,我在部环境。今天这篇文章缕一下在同一台服...【详细内容】
2021-12-08  Tags: MySQL  点击:(16)  评论:(0)  加入收藏
对于数据分析来说,MySQL使用最多的是查询,比如对数据进行排序、分组、去重、汇总及字符串匹配等,如果查询的数据涉及多个表,还需要要对表进行连接,本文就来说说MySQL中常用的查询...【详细内容】
2021-12-06  Tags: MySQL  点击:(19)  评论:(0)  加入收藏
在学习SQL语句之前,首先需要区分几个概念,我们常说的数据库是指数据库软件,例如MySQL、Oracle、SQL Server等,而本文提到的数据库是指数据库软件中的一个个用于存储数据的容器。...【详细内容】
2021-11-24  Tags: MySQL  点击:(23)  评论:(0)  加入收藏
概述以前参加过一个库存系统,由于其业务复杂性,搞了很多个应用来支撑。这样的话一份库存数据就有可能同时有多个应用来修改库存数据。比如说,有定时任务域xx.cron,和SystemA域...【详细内容】
2021-11-05  Tags: MySQL  点击:(31)  评论:(0)  加入收藏
▌简易百科推荐
作者:雷文霆 爱可生华东交付服务部 DBA 成员,主要负责Mysql故障处理及相关技术支持。爱好看书,电影。座右铭,每一个不曾起舞的日子,都是对生命的辜负。 本文来源:原创投稿 *爱可生...【详细内容】
2021-12-24  爱可生    Tags:MySQL   点击:(6)  评论:(0)  加入收藏
生成间隙(gap)锁、临键(next-key)锁的前提条件 是在 RR 隔离级别下。有关Mysql记录锁、间隙(gap)锁、临键锁(next-key)锁的一些理论知识之前有写过,详细内容可以看这篇文章...【详细内容】
2021-12-14  python数据分析    Tags:MySQL记录锁   点击:(17)  评论:(0)  加入收藏
binlog 基本认识 MySQL的二进制日志可以说是MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二...【详细内容】
2021-12-14  linux上的码农    Tags:mysql   点击:(13)  评论:(0)  加入收藏
为查询优化你的查询 大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查...【详细内容】
2021-12-09  元宇宙iwemeta    Tags:mysql   点击:(15)  评论:(0)  加入收藏
测试的目的和原因,公司有很多程序员,每个程序员对数据库和表结构都有自己的理解。而且每个程序员的理解往往是以效率考虑。既然都是为了效率考虑,那么我就来测试一下究竟哪种使...【详细内容】
2021-12-08  吴彬的分享    Tags:Mysql数据库   点击:(14)  评论:(0)  加入收藏
当你们考虑项目并发的时候,我在部署环境,当你们在纠结使用ArrayList还是LinkedArrayList的时候,我还是在部署环境。所以啊,技术不止境,我在部环境。今天这篇文章缕一下在同一台服...【详细内容】
2021-12-08  秃头码哥    Tags:MySQL数据库   点击:(16)  评论:(0)  加入收藏
对于数据分析来说,MySQL使用最多的是查询,比如对数据进行排序、分组、去重、汇总及字符串匹配等,如果查询的数据涉及多个表,还需要要对表进行连接,本文就来说说MySQL中常用的查询...【详细内容】
2021-12-06  笨鸟学数据分析    Tags:MySQL   点击:(19)  评论:(0)  加入收藏
在学习SQL语句之前,首先需要区分几个概念,我们常说的数据库是指数据库软件,例如MySQL、Oracle、SQL Server等,而本文提到的数据库是指数据库软件中的一个个用于存储数据的容器。...【详细内容】
2021-11-24  笨鸟学数据分析    Tags:SQL语句   点击:(23)  评论:(0)  加入收藏
概述以前参加过一个库存系统,由于其业务复杂性,搞了很多个应用来支撑。这样的话一份库存数据就有可能同时有多个应用来修改库存数据。比如说,有定时任务域xx.cron,和SystemA域...【详细内容】
2021-11-05  Java云海    Tags:分布式锁   点击:(31)  评论:(0)  加入收藏
MySQL的进阶查询 一、 按关键字排序 使用ORDERBY语句来实现排序排序可针对一个或多个字段ASC:升序,默认排序方式 【升序是从小到大】DESC:降序 【降序是从大到小】ORDER BY的...【详细内容】
2021-11-05  Java热点    Tags:SQL语句   点击:(27)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条