Oracle listagg去重distinct的三种方式总结

目录
  • 一、简介
  • 二、方法
    • 【a】 第一种方法
    • 【b】第二种方法
    • 【c】第三种方法
  • 三、总结

一、简介

最近在工作中,在写oracle统计查询的时候,遇到listagg聚合函数分组聚合之后出现很多重复数据的问题,于是研究了一下listagg去重的几种方法

以下通过实例讲解三种实现listagg去重的方法。

二、方法

首先还原listagg聚合之后出现重复数据的现象,打开plsql,执行如下sql:

select t.department_name depname,
       t.department_key,
       listagg(t.class_key, ',') within group(order by t.class_key) as class_keys
  from V_YDXG_TEACHER_KNSRDGL t
 where 1 = 1
 group by t.department_key, t.department_name

运行结果:

如图,listagg聚合之后很多重复数据,下面讲解如何解决重复数据问题。

【a】 第一种方法

使用wm_concat() + distinct去重聚合

--第一种方法: 使用wm_concat() + distinct去重聚合
select t.department_name depname,
       t.department_key,
       wm_concat(distinct t.class_key) as class_keys
  from V_YDXG_TEACHER_KNSRDGL t
 where 1 = 1
 group by t.department_key, t.department_name

如上图,listagg聚合之后没有出现重复数据了。oracle官方不太推荐使用wm_concat()来进行聚合,能尽量使用listagg就使用listagg。

【b】第二种方法

使用正则替换方式去重(仅适用于oracle字符串大小比较小的情况)

--第二种方法:使用正则替换方式去重(仅适用于oracle字符串大小比较小的情况)
select t.department_name depname,
       t.department_key,
       regexp_replace(listagg(t.class_key, ',') within
                      group(order by t.class_key),
                      '([^,]+)(,\1)*(,|$)',
                      '\1\3') as class_keys
  from V_YDXG_TEACHER_KNSRDGL t
 group by t.department_key, t.department_name;

这种方式处理listagg去重问题如果拼接的字符串太长会报oracle超过最大长度的错误,只适用于数据量比较小的场景。

【c】第三种方法

先去重,再聚合(推荐使用)

--第三种方法:先去重,再聚合
select t.department_name depname,
       t.department_key,
       listagg(t.class_key, ',') within group(order by t.class_key) as class_keys
  from (select distinct s.class_key, s.department_key, s.department_name
          from V_YDXG_TEACHER_KNSRDGL s) t
 group by t.department_key, t.department_name

--或者
select s.department_key,
       s.department_name,
       listagg(s.class_key, ',') within group(order by s.class_key) as class_keys
  from (select t.department_key,
               t.department_name,
               t.class_key,
               row_number() over(partition by t.department_key, t.department_name, t.class_key order by t.department_key, t.department_name) as rn
          from V_YDXG_TEACHER_KNSRDGL t
         order by t.department_key, t.department_name, t.class_key) s
 where rn = 1
 group by s.department_key, s.department_name;
 

推荐使用这种方式,先把重复数据去重之后再进行聚合处理。

三、总结

以上就是关于listagg聚合函数去重的三种处理方法的总结,本文仅仅是笔者的一些总结和见解,仅供大家学习参考,希望能对大家有所帮助。也希望大家多多支持我们。

时间: 2022-11-17

Oracle删除重复的数据,Oracle数据去重复

Oracle  数据库中查询重复数据: select * from employee group by emp_name having count (*)>1;  Oracle  查询可以删除的重复数据 select t1.* from employee t1 where (t1.emp_name) in (SELECT t2.emp_name from employee t2 group by emp_name having count (*)>1) and t1.emp_id not in

Oracle表中重复数据去重的方法实例详解

Oracle表中重复数据去重的方法实例详解 我们在项目中肯定会遇到一种情况,就是表中没有主键 有重复数据 或者有主键 但是部分字段有重复数据 而我们需要过滤掉重复数据 下面是一种解决方法 delete from mytest ms where rowid in (select aa.rid from (select rowid as rid, row_number() over(partition by s.name order by s.id) as nu from mytest s) aa

oracle sql 去重复记录不用distinct如何实现

用distinct关键字只能过滤查询字段中所有记录相同的(记录集相同),而如果要指定一个字段却没有效果,另外distinct关键字会排序,效率很低 . select distinct name from t1 能消除重复记录,但只能取一个字段,现在要同时取id,name这2个字段的值. select distinct id,name from t1 可以取多个字段,但只能消除这2个字段值全部相同的记录 所以用distinct达不到想要的效果,用group by 可以解决这个问题. 例如要显示的字

ORACLE查询删除重复记录三种方法

比如现在有一人员表 (表名:peosons) 若想将姓名.身份证号.住址这三个字段完全相同的记录查询出来 复制代码 代码如下: select p1.*   from persons  p1,persons  p2   where p1.id<>p2.id   and  p1.cardid = p2.cardid and p1.pname = p2.pname and p1.address = p2.address 可以实现上述效果. 几个删除重复记录的SQL语句 1.用rowid方法 2.用g

SQL去除重复记录(七种)

话不多说,请看代码: if not object_id('Tempdb..#T') is null drop table #T Go Create table #T([ID] int,[Name] nvarchar(1),[Memo] nvarchar(2)) Insert #T select 1,N'A',N'A1' union all select 2,N'A',N'A2' union all select 3,N'A',N'A3' union all select 4,N'B',N'B1'

MySQL中distinct语句去查询重复记录及相关的性能讨论

在 MySQL 查询中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值. 关键词 DISTINCT 用于返回唯一不同的值,就是去重啦.用法也很简单: SELECT DISTINCT * FROM tableName DISTINCT 这个关键字来过滤掉多余的重复记录只保留一条. 另外,如果要对某个字段去重,可以试下: SELECT *, COUNT(DISTINCT nowamagic) FROM table GROUP BY nowamagic 这个用

oracle查询重复数据和删除重复记录示例分享

一.查询某个字段重复 select * from User u where u.user_name in (select u.user_name from User u group by u.user_name having count(*) > 1) 二,删除表中某几个字段的重复 例:表中有条六条记录.   其中张三和王五   的记录有重复 TableA id customer PhoneNo 001 张三 777777 002 李四 444444 003 王五 555555 004 张三 7

oracle快速删除重复的记录

正在看的ORACLE教程是:oracle快速删除重复的记录.做项目的时候,一位同事导数据的时候,不小心把一个表中的数据全都搞重了,也就是说,这个表里所有的记录都有一条重复的.这个表的数据是千万级的,而且是生产系统.也就是说,不能把所有的记录都删除,而且必须快速的把重复记录删掉. 对此,总结了一下删除重复记录的方法,以及每种方法的优缺点. 为了陈诉方便,假设表名为Tbl,表中有三列col1,col2,col3,其中col1,col2是主键,并且,col1,col2上加了索引. 1.通过创建临时表

使用distinct在mysql中查询多条不重复记录值的解决办法

在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的所有值.其原因是distinct只能返回它的目标字段,而无法返回其它字段,这个问题让我困扰了很久,用distinct不能解决的话,我只有用二重循环查询来解决,而这样对于一个数据量非常大的站来说,无疑是会直接影响到效率的.所以我花了很多时间来研究这个问题,网上也查不到解决方案,期间把容容拉来帮忙,结果是

解析mysql中:单表distinct、多表group by查询去除重复记录

单表的唯一查询用:distinct多表的唯一查询用:group bydistinct 查询多表时,left join 还有效,全连接无效,在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重复记录的所有值.其原因是distinct只能返回它的目标字段,而无法返回其它字段,用distinct不能解决的话,我只有用二重循环查询来解决,而这样对于一个数据量非常大的

SQL对冗余数据的删除重复记录只保留单条的说明

我们先看一下相关数据结构的知识. 在学习线性表的时候,曾有这样一个例题. 已知一个存储整数的顺序表La,试构造顺序表Lb,要求顺序表Lb中只包含顺序表La中所有值不相同的数据元素. 算法思路: 先把顺序表La的第一个元素付给顺序表Lb,然后从顺序表La的第2个元素起,每一个元素与顺序表Lb中的每一个元素进行比较,如果不相同,则把该元素附加到顺序表Lb的末尾. 复制代码 代码如下: public SeqList<int> Purge(SeqList<int> La) { SeqLis