0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何查找多列上的重复行

我快闭嘴 来源:CSDN技术社区 作者:CSDN技术社区 2022-09-14 09:05 次阅读

		

如何查找重复行

第一步是定义什么样的行才是重复行。多数情况下很简单:它们某一列具有相同的值。本文采用这一定义,或许你对“重复”的定义比这复杂,你需要对sql做些修改。本文要用到的数据样本:

createtabletest(idintnotnullprimarykey,daydatenotnull);

insertintotest(id,day)values(1,'2006-10-08');
insertintotest(id,day)values(2,'2006-10-08');
insertintotest(id,day)values(3,'2006-10-09');

select*fromtest;
+----+------------+
|id|day|
+----+------------+
|1|2006-10-08|
|2|2006-10-08|
|3|2006-10-09|
+----+------------+

前面两行在day字段具有相同的值,因此如何我将他们当做重复行,这里有一查询语句可以查找。查询语句使用GROUP BY子句把具有相同字段值的行归为一组,然后计算组的大小。

selectday,count(*)fromtestGROUPBYday;
+------------+----------+
|day|count(*)|
+------------+----------+
|2006-10-08|2|
|2006-10-09|1|
+------------+----------+

重复行的组大小大于1。如何希望只显示重复行,必须使用HAVING子句,比如

selectday,count(*)fromtestgroupbydayHAVINGcount(*)>1;
+------------+----------+
|day|count(*)|
+------------+----------+
|2006-10-08|2|
+------------+----------+

这是基本的技巧:根据具有相同值的字段分组,然后知显示大小大于1的组。

为什么不能使用WHERE子句?因为WHERE子句过滤的是分组之前的行,HAVING子句过滤的是分组之后的行。

如何删除重复行

一个相关的问题是如何删除重复行。一个常见的任务是,重复行只保留一行,其他删除,然后你可以创建适当的索引,防止以后再有重复的行写入数据库。

同样,首先是弄清楚重复行的定义。你要保留的是哪一行呢?第一行,或者某个字段具有最大值的行?本文中,假设要保留的是第一行——id字段具有最小值的行,意味着你要删除其他的行。

也许最简单的方法是通过临时表。尤其对于MYSQL,有些限制是不能在一个查询语句中select的同时update一个表。简单起见,这里只用到了临时表的方法。

我们的任务是:删除所有重复行,除了分组中id字段具有最小值的行。因此,需要找出大小大于1的分组,以及希望保留的行。你可以使用MIN()函数。这里的语句是创建临时表,以及查找需要用DELETE删除的行。

createtemporarytableto_delete(daydatenotnull,min_idintnotnull);

insertintoto_delete(day,min_id)
selectday,MIN(id)fromtestgroupbydayhavingcount(*)>1;

select*fromto_delete;
+------------+--------+
|day|min_id|
+------------+--------+
|2006-10-08|1|
+------------+--------+

有了这些数据,你可以开始删除“脏数据”行了。可以有几种方法,各有优劣,只是说明在支持查询子句的关系数据库中,使用的标准方法。

deletefromtest
whereexists(
select*fromto_delete
whereto_delete.day=test.dayandto_delete.min_id<>test.id
)

如何查找多列上的重复行

有人最近问到这样的问题:我的一个表上有两个字段b和c,分别关联到其他两个表的b和c字段。我想要找出在b字段或者c字段上具有重复值的行。

咋看很难明白,通过对话后我理解了:他想要对b和c分别创建unique索引。如上所述,查找在某一字段上具有重复值的行很简单,只要用group分组,然后计算组的大小。并且查找全部字段重复的行也很简单,只要把所有字段放到group子句。但如果是判断b字段重复或者c字段重复,问题困难得多。这里提问者用到的样本数据

createtablea_b_c(
aintnotnullprimarykeyauto_increment,
bint,
cint
);

insertintoa_b_c(b,c)values(1,1);
insertintoa_b_c(b,c)values(1,2);
insertintoa_b_c(b,c)values(1,3);
insertintoa_b_c(b,c)values(2,1);
insertintoa_b_c(b,c)values(2,2);
insertintoa_b_c(b,c)values(2,3);
insertintoa_b_c(b,c)values(3,1);
insertintoa_b_c(b,c)values(3,2);
insertintoa_b_c(b,c)values(3,3);

现在,你可以轻易看到表里面有一些重复的行,但找不到两行具有相同的二元组{b, c}。这就是为什么问题会变得困难了。

错误的查询语句

如果把两列放在一起分组,你会得到不同的结果,具体看如何分组和计算大小。提问者恰恰是困在了这里。有时候查询语句找到一些重复行却漏了其他的。这是他用到了查询

selectb,c,count(*)froma_b_c
groupbyb,c
havingcount(distinctb>1)
orcount(distinctc>1);

结果返回所有的行,因为CONT(*)总是1.为什么?因为 >1 写在COUNT()里面。这个错误很容易被忽略,事实上等效于

selectb,c,count(*)froma_b_c
groupbyb,c
havingcount(1)
orcount(1);

为什么?因为(b > 1)是一个布尔值,根本不是你想要的结果。你要的是

selectb,c,count(*)froma_b_c
groupbyb,c
havingcount(distinctb)>1
orcount(distinctc)>1;

返回空结果。很显然,因为没有重复的{b,c}。这人试了很多其他的OR和AND的组合,用来分组的是一个字段,计算大小的是另一个字段,像这样

selectb,count(*)froma_b_cgroupbybhavingcount(distinctc)>1;
+------+----------+
|b|count(*)|
+------+----------+
|1|3|
|2|3|
|3|3|
+------+----------+

没有一个能够找出全部的重复行。而且最令人沮丧的是,对于某些情况,这种语句是有效的,如果错误地以为就是这么写法,然而对于另外的情况,很可能得到错误结果。

事实上,单纯用GROUP BY 是不可行的。为什么?因为当你对某一字段使用group by时,就会把另一字段的值分散到不同的分组里。对这些字段排序可以看到这些效果,正如分组做的那样。首先,对b字段排序,看看它是如何分组的

43d98dca-33bd-11ed-ba43-dac502259ad0.png

当你对b字段排序(分组),相同值的c被分到不同的组,因此不能用COUNT(DISTINCT c)来计算大小。COUNT()之类的内部函数只作用于同一个分组,对于不同分组的行就无能为力了。类似,如果排序的是c字段,相同值的b也会分到不同的组,无论如何是不能达到我们的目的的。

几种正确的方法

也许最简单的方法是分别对某个字段查找重复行,然后用UNION拼在一起,像这样:

selectbasvalue,count(*)ascnt,'b'aswhat_col
froma_b_cgroupbybhavingcount(*)>1
union
selectcasvalue,count(*)ascnt,'c'aswhat_col
froma_b_cgroupbychavingcount(*)>1;
+-------+-----+----------+
|value|cnt|what_col|
+-------+-----+----------+
|1|3|b|
|2|3|b|
|3|3|b|
|1|3|c|
|2|3|c|
|3|3|c|
+-------+-----+----------+

输出what_col字段为了提示重复的是哪个字段。另一个办法是使用嵌套查询:

selecta,b,cfroma_b_c
wherebin(selectbfroma_b_cgroupbybhavingcount(*)>1)
orcin(selectcfroma_b_cgroupbychavingcount(*)>1);
+----+------+------+
|a|b|c|
+----+------+------+
|7|1|1|
|8|1|2|
|9|1|3|
|10|2|1|
|11|2|2|
|12|2|3|
|13|3|1|
|14|3|2|
|15|3|3|
+----+------+------+

这种方法的效率要比使用UNION低许多,并且显示每一重复的行,而不是重复的字段值。还有一种方法,将自己跟group的嵌套查询结果联表查询。写法比较复杂,但对于复杂的数据或者对效率有较高要求的情况,是很有必要的。

selecta,a_b_c.b,a_b_c.c
froma_b_c
leftouterjoin(
selectbfroma_b_cgroupbybhavingcount(*)>1
)asbona_b_c.b=b.b
leftouterjoin(
selectcfroma_b_cgroupbychavingcount(*)>1
)ascona_b_c.c=c.c
whereb.bisnotnullorc.cisnotnull

以上方法可行,我敢肯定还有其他的方法。如果UNION能用,我想会是最简单不过的了。


审核编辑:汤梓红


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • MySQL
    +关注

    关注

    1

    文章

    801

    浏览量

    26437

原文标题:MySQL 如何查找删除重复行?

文章出处:【微信号:良许Linux,微信公众号:良许Linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何用C语言实现高效查找(二分法)

    (BinarySearch),是一种效率较高的查找方法。有序且不重复的数组中的元素的查找。intfindNumIndex(int*arr,intlen,intn){intend=l
    的头像 发表于 06-04 08:04 944次阅读
    如何用C语言实现高效<b class='flag-5'>查找</b>(二分法)

    STM32没有重复定义却报重复定义是怎么回事?

    STM32H743用keil v5编译,上报重复定义: 通过全工程查找 __stdout,却没有发现重复定义,麻烦帮我看看是怎么回事,谢谢!
    发表于 03-08 08:12

    列列表框的方法节点“获取双击的”怎么使用?

    现在要使用列列表框里“获取双击的”这个方法节点,但是我怎么弄这个方法节点输出都是-2,不会变啊?请高手赐教!
    发表于 05-15 14:49

    labview 列列表框 删除

    没办法上传图片,我叙述下要求:就是有一个列列表框,我想通过鼠标,可以任意删除某一数据,不知道如何才能实现
    发表于 12-15 15:59

    labview怎么删除列列表框的

    labview怎么删除列列表框的
    发表于 04-19 16:03

    列列表框 颜色

    如何使用列列表框时其中的某一列按照特定的字符改变整行的颜色。表格不同的根据特定的条件有多种颜色显示该行:条件1、红色条件2、绿色条件3、蓝色条件4、橙色其他、白色
    发表于 07-26 17:02

    请问队列上锁与解锁是什么意思?

    请问队列上锁与解锁是什么意思?它的实际意义又在哪里呢??想不明白
    发表于 07-19 08:03

    Kinetis E系列上的UART引导加载程序设计资料分享

    Kinetis E系列上的UART引导加载程序设计 - 应用说明
    发表于 12-12 06:51

    原创:Labview找出数组重复元素和重复元素的全部索引

    *附件:查找重复元素.rar
    发表于 06-27 09:22

    Kinetis E系列上的UART引导加载程序设计

    Kinetis E系列上的UART引导加载程序设计
    发表于 11-02 10:56 4次下载

    OpenFlow流表查找方法

    基于TCAM的OpenFlow流表查找具有较高的成本与能耗。为了降低流表查找的成本与能耗,提出了单元散列表与TCAM结合的OpenFlow流表存储与查找的方法。通过理论分析与仿真测试
    发表于 02-06 14:42 0次下载
    OpenFlow流表<b class='flag-5'>查找</b>方法

    重复接地是什么意思_重复接地的作用有哪些

    本文首先介绍了重复接地的概念,其次介绍了重复接地的优点,最后介绍了重复接地的作用。
    的头像 发表于 01-03 08:59 2.9w次阅读

    FPGA查找表LUT和编程方式的基础知识说明

    工艺的查找表结构,也有一些军品和宇航级FPGA采用Flash或者熔丝与反熔丝工艺的查找表结 构。通过烧写文件改变查找表内容的方法来实现对FPGA的重复配置。
    发表于 12-29 17:27 16次下载

    重复1175

    重复1175
    发表于 04-24 13:35 1次下载
    <b class='flag-5'>重复</b><b class='flag-5'>行</b>1175

    vlookup怎么把第二个重复值显示

    VLOOKUP是Excel中最常用的函数之一,它可以根据给定的值在数据表中查找相应的信息。然而,当数据表中存在重复查找值时,VLOOKUP只能返回第一个匹配结果的数据。在本文中,我们将介绍
    的头像 发表于 12-03 10:24 2995次阅读