Oracle 根据某个字段对查询结果去重 三种方法详述

Oracle三种去重的方法

  • distinct
  • group by
  • rowid

分组函数:作用于一组数据,并对一组数据返回一个值

常见的分组函数有:
count 返回找到的记录数
min 返回一个数字列或计算列的最小值
max 返回一个数字列或计算列的最大值
sum 返回一个数字列或计算列总和
avg 返回一个数字列或计算列的平均值

一、distinct

distinct 单列
select distinct(a) from tableA;
distinct 多列
--会报错,distinct 必须放在 select 语句的最前方
select a, distinct b,c from tableA;
select distinct a,b,c from tableA;

多列的时候,上述语句是针对abc的组合来distinct的,列出的是abc的所有不同组合,相当于下列语句

select a,b,c from tableA group by a,b,c;

那么,如果想要分别查询a,b,c三个字段的distinct值怎么办?一开始可能只想到下列三个语句

select distinct a from tableA;
select distinct b from tableA;
select distinct c from tableA;

麻烦,如何合并成一个语句呢,使用union解决,后面拼接的字符串是为了标识这个值属于哪个字段:

select distinct(a) || ' a' from tableA
union all
select distinct(b) || ' b' from tableA
union all
select distinct(c) || ' c' from tableA

二、group by

只查询非分组函数,不需要使用group by
select Name, Gender from dba_data_files;
只要查询了分组函数,就需要使用group by
  1. 只查询分组函数的话,group by的子句里用到的列名Name 和 Gender,不需要写在select里;但select里出现别的列就会报错;
select sum(Age) from dba_data_files group by Name, Gender;

-- 但 select 里出现别的列就会报错,例:
select Weight, sum(Age) from dba_data_files group by Name, Gender;
  1. 同时查询分组函数和非分组函数,并且必须将分组函数以外的所有的列(Name 和 Gender),都写到group by里,少一个都不行;
select Name, Gender, sum(Age) from dba_data_files group by Name, Gender;

不管select是否使用了where子句,都可以使用group by子句

三、rowid

rowid简介

rowid是一个用来唯一标记表中行的伪列。它是物理表中行数据的内部地址,包含两个地址,其一为指向数据表中包含该行的块所存放数据文件的地址,另一个是可以直接定位到数据行自身的这一行在数据块中的地址。
除了在同一聚簇中可能不唯一外,每条记录的rowid是唯一的。可以理解成rowid就是唯一的。

rowid解析

从Oracle 8i开始使用扩展rowid标识行物理地址
扩展rowid使用base64编码行的物理地址,编码字符包含A-Z, a-z, 0-9, +, 和/。
扩展rowid由四部分组成:OOOOOOOFFFBBBBBBRRR:
rowid包含如下内容:
①:对象所在的数据文件号
②:对象所在的块号
③:对象所在行在块内的位置
④:对象号
其中:
OOOOOO:数据对象编号(6位显示)
FFF:相关数据文件编号(3位显示)
BBBBBB:数据块编号(6位显示)
RRR:数据块中行编号(3位显示)
在这里插入图片描述

rowid示例

利用rowid结合maxmin函数快速去重

select t.* from bill t where t.rowid = (select max(s.rowid) from bill s 
where t.FLAG = s.FLAG
  and s.btype = 1
  and s.CODE in ('71131702422','71130427253','71134427859')
);

利用rowid结合maxmin函数快速删除重复数据

-- 使用min函数的时候用大于号>
delete t.* from bill t where t.rowid < (select max(s.rowid) from bill s 
where t.FLAG = s.FLAG
  and s.btype = 1
  and s.CODE in ('71131702422','71130427253','71134427859')
);

本文参考链接1.

Mysql里,可以用Max函数,类似于Oraclerowidmax
SQL Server中也有First_ValueLast_Value函数,可以用来实现。

注:group by 必须放在 order by 和 limit之前,不然会报错

  • 13
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值