热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

面试必备:如何实现SQL语句删除重复记录且只保留一条有效记录?

最近在做题库系统,由于在题库中添加了重复的试题,所以需要查询出重复的试题,并且删除掉重复的试题只保留其中1条,以保证考试的时

最近在做题库系统,由于在题库中添加了重复的试题,所以需要查询出重复的试题,并且删除掉重复的试题只保留其中1条,以保证考试的时候抽不到重复的题。

首先写了一个小的例子:

一、单个字段的操作

这是数据库中的表:

23e7d4fcbccb3ea5454a589b65f3c6f6.jpeg

分组介绍

39de796efa1c9f1c9b6fff9f8ae442f7.jpeg

Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1

查看是否有重复的数据:

  • GROUP BY <列名序列>

  • HAVING <组条件表达式>

查询出&#xff1a;根据dname分组&#xff0c;同时满足having字句中组条件表达式&#xff08;重复次数大于1&#xff09;的那些组

count(*)与count(1) 其实没有什么差别&#xff0c;用哪个都可以

count(*)与count&#xff08;列名&#xff09;的区别&#xff1a;

count(*)将返回表格中所有存在的行的总数包括值为null的行&#xff0c;然而count(列名)将返回表格中除去null以外的所有行的总数(有默认值的列也会被计入&#xff09;

1、 查询全部重复的数据

1e374bb501fdecfbab6e7f10a69034c2.jpeg

Select * From 表 Where 重复字段 In (Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1)

2、删除全部重复试题

将上面的查询select改为delete&#xff08;这样会出错的&#xff09;。面试宝典&#xff1a;www.yoodb.com

DELETE
FROMdept
WHEREdname IN (SELECTdnameFROMdeptGROUP BYdnameHAVINGcount(1) > 1)

会出现如下错误&#xff1a;[Err] 1093 - You can&#39;t specify target table &#39;dept&#39; for update in FROM clause

原因是&#xff1a;更新这个表的同时又查询了这个表&#xff0c;查询这个表的同时又去更新了这个表&#xff0c;可以理解为死锁。mysql不支持这种更新查询同一张表的操作

解决办法&#xff1a;把要更新的几列数据查询出来做为一个第三方表&#xff0c;然后筛选更新。

90ca76a7bc525335136072aa559d3163.jpeg

3、查询表中多余重复试题&#xff08;根据depno来判断&#xff0c;除了rowid最小的一个&#xff09;

a. 第一种方法&#xff1a;

0499104792c972f5c6d92893b01b1487.jpeg

SELECT*
FROMdept
WHEREdname IN (SELECTdnameFROMdeptGROUP BYdnameHAVINGCOUNT(1) > 1)
AND deptno NOT IN (SELECTMIN(deptno)FROMdeptGROUP BYdnameHAVINGCOUNT(1) > 1
)

上面这种写法正确&#xff0c;但是查询的速度太慢&#xff0c;可以试一下下面这种方法&#xff1a;

b. 第二种方法&#xff1a;

☆根据dname分组&#xff0c;查找出deptno最小的。然后再查找deptno不包含刚才查出来的。这样就查询出了所有的重复数据&#xff08;除了deptno最小的那行&#xff09;。

SELECT *
FROMdept
WHEREdeptno NOT IN (SELECTdt.minnoFROM(SELECTMIN(deptno) AS minnoFROMdeptGROUP BYdname) dt)

c. 补充第三种方法&#xff1a;

SELECT* 
FROMtable_name AS ta 
WHEREta.唯一键 <> ( SELECT max( tb.唯一键 ) FROM table_name AS tb WHERE ta.判断重复的列 &#61; tb.判断重复的列 );

4、删除表中多余重复试题并且只留1条

a. 第一种方法&#xff1a;

DELETE
FROMdept
WHEREdname IN (SELECTt.dnameFROM(SELECTdnameFROMdeptGROUP BYdnameHAVINGcount(1) > 1) t)
AND deptno NOT IN (
SELECTdt.mindeptno
FROM(SELECTmin(deptno) AS mindeptnoFROMdeptGROUP BYdnameHAVINGcount(1) > 1) dt
)

b. ☆第二种方法&#xff08;与上面查询的第二种方法对应&#xff0c;只是将select改为delete&#xff09;&#xff1a;

DELETE
FROMdept
WHEREdeptno NOT IN (SELECTdt.minnoFROM(SELECTMIN(deptno) AS minnoFROMdeptGROUP BYdname) dt)

c. 补充第三种方法&#xff08;评论区推荐的一种方法&#xff09;&#xff1a;

DELETE 
FROMtable_name AS ta 
WHEREta.唯一键 <> (
SELECTt.maxid 
FROM( SELECT max( tb.唯一键 ) AS maxid FROM table_name AS tb WHERE ta.判断重复的列 &#61; tb.判断重复的列 ) t );

二、多个字段的操作

单个字段的如果会了&#xff0c;多个字段也非常简单。就是将group by 的字段增加为你想要的即可。

此处只写一个&#xff0c;其他方法请仿照一个字段的写即可。

DELETE
FROMdept
WHERE(dname, db_source) IN (SELECTt.dname,t.db_sourceFROM(SELECTdname,db_sourceFROMdeptGROUP BYdname,db_sourceHAVINGcount(1) > 1) t)
AND deptno NOT IN (SELECTdt.mindeptnoFROM(SELECTmin(deptno) AS mindeptnoFROMdeptGROUP BYdname,db_sourceHAVINGcount(1) > 1) dt
)

总结

其实上面的方法还有很多需要优化的地方&#xff0c;如果数据量太大的话&#xff0c;执行起来很慢&#xff0c;可以考虑加优化一下&#xff1a;

  • 在经常查询的字段上加上索引

  • 将*改为你需要查询出来的字段&#xff0c;不要全部查询出来

  • 小表驱动大表用IN&#xff0c;大表驱动小表用EXISTS。IN适合的情况是外表数据量小的情况&#xff0c;而不是外表数据大的情况&#xff0c;因为IN会遍历外表的全部数据&#xff0c;假设a表100条&#xff0c;b表10000条那么遍历次数就是100*10000次&#xff0c;而exists则是执行100次去判断a表中的数据是否在b表中存在&#xff0c;它只执行了a.length次数。至于哪一个效率高是要看情况的&#xff0c;因为in是在内存中比较的&#xff0c;而exists则是进行数据库查询操作的

作者&#xff1a;千g

blog.csdn.net/n950814abc/article/details/82284838

公众号“Java精选”所发表内容注明来源的&#xff0c;版权归原出处所有&#xff08;无法查证版权的或者未注明出处的均来自网络&#xff0c;系转载&#xff0c;转载的目的在于传递更多信息&#xff0c;版权属于原作者。如有侵权&#xff0c;请联系&#xff0c;笔者会第一时间删除处理&#xff01;
最近有很多人问&#xff0c;有没有读者交流群&#xff01;加入方式很简单&#xff0c;公众号Java精选&#xff0c;回复“加群”&#xff0c;即可入群&#xff01;Java精选面试题&#xff08;微信小程序&#xff09;&#xff1a;3000&#43;道面试题&#xff0c;包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计等&#xff0c;在线随时刷题&#xff01;
------ 特别推荐 ------
特别推荐&#xff1a;专注分享最前沿的技术与资讯&#xff0c;为弯道超车做好准备及各种开源项目与高效率软件的公众号&#xff0c;「大咖笔记」&#xff0c;专注挖掘好东西&#xff0c;非常值得大家关注。点击下方公众号卡片关注。点击“阅读原文”&#xff0c;了解更多精彩内容&#xff01;文章有帮助的话&#xff0c;点在看&#xff0c;转发吧&#xff01;


推荐阅读
author-avatar
訫梦沁_245
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有