社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

京东笔试题:如何实现 MySQL 删除重复记录并且只保留一条?

架构师大咖 • 2 年前 • 303 次点击  
👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇
作者:千g
来源:blog.csdn.net/n950814abc/article/details/82284838

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

首先写了一个小的例子:

一、单个字段的操作


这是数据库中的表:

分组介绍


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

查看是否有重复的数据:

  • GROUP BY

  • HAVING


查询出:根据dname分组,同时满足having字句中组条件表达式(重复次数大于1)的那些组

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

count(*)与count(列名)的区别:

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

1. 查询全部重复的数据



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


2. 删除全部重复试题


将上面的查询select改为delete(这样会出错的)
DELETEFROM deptWHERE dname IN (  SELECT   dname  FROM   dept  GROUP BY   dname  HAVING   count(1) > 1 )
会出现如下错误:[Err] 1093 - You can't specify target table 'dept' for update in FROM clause

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

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


3. 查询表中多余重复试题(根据depno来判断,除了rowid最小的一个)


a. 第一种方法

SELECT *


    
FROM deptWHERE dname IN (  SELECT   dname  FROM   dept  GROUP BY   dname  HAVING   COUNT(1) > 1 )AND deptno NOT IN ( SELECT  MIN(deptno) FROM  dept GROUP BY  dname


    
 HAVING  COUNT(1) > 1)
上面这种写法正确,但是查询的速度太慢,可以试一下下面这种方法:

b. 第二种方法


根据dname分组,查找出deptno最小的。然后再查找deptno不包含刚才查出来的。这样就查询出了所有的重复数据(除了deptno最小的那行)。
SELECT *FROM deptWHERE deptno NOT IN (  SELECT   dt.minno  FROM   (    SELECT     MIN(deptno) AS minno    FROM     dept


    
    GROUP BY     dname   ) dt )


c. 补充第三种方法


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


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


a. 第一种方法:

DELETEFROM deptWHERE dname IN (  SELECT   t.dname  FROM   (    SELECT     dname


    
    FROM     dept    GROUP BY     dname    HAVING     count(1) > 1   ) t )AND deptno NOT IN (SELECT dt.mindeptnoFROM (  SELECT   min(deptno) AS mindeptno  FROM   dept  GROUP BY   dname  HAVING


    
   count(1) > 1 ) dt)


b. 第二种方法(与上面查询的第二种方法对应,只是将select改为delete)

DELETEFROM deptWHERE deptno NOT IN (  SELECT   dt.minno  FROM   (    SELECT     MIN(deptno) AS minno    FROM     dept    GROUP BY     dname


    
   ) dt )


c. 补充第三种方法(评论区推荐的一种方法)

DELETE FROM table_name AS ta WHERE ta.唯一键 <> (SELECT t.maxid FROM ( SELECT max( tb.唯一键 ) AS maxid FROM table_name AS tb WHERE ta.判断重复的列 = tb.判断重复的列 ) t  );


二、多个字段的操作


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

此处只写一个,其他方法请仿照一个字段的写即可。
DELETEFROM deptWHERE (dname, db_source) IN (  SELECT   t.dname,   t.db_source  FROM   (    SELECT


    
     dname,     db_source    FROM     dept    GROUP BY     dname,     db_source    HAVING     count(1) > 1   ) t )AND deptno NOT IN ( SELECT  dt.mindeptno FROM  (   SELECT    min(deptno) AS mindeptno   FROM    dept   GROUP


    
 BY    dname,    db_source   HAVING    count(1) > 1  ) dt)


# 总结


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

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

  • 将*改为你需要查询出来的字段,不要全部查询出来

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

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

点击👆卡片,关注后回复【面试题】即可获取

在看点这里好文分享给更多人↓↓

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/150097
 
303 次点击