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

一、简介

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

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

二、方法

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

1

2

3

4

5

6

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

运行结果:

Oracle listagg去重distinct的三种方式总结_第1张图片

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

【a】 第一种方法

使用wm_concat() + distinct去重聚合

1

2

3

4

5

6

7

--第一种方法: 使用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

Oracle listagg去重distinct的三种方式总结_第2张图片

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

【b】第二种方法

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

1

2

3

4

5

6

7

8

9

--第二种方法:使用正则替换方式去重(仅适用于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;

Oracle listagg去重distinct的三种方式总结_第3张图片

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

【c】第三种方法

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

--第三种方法:先去重,再聚合

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;

Oracle listagg去重distinct的三种方式总结_第4张图片

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

你可能感兴趣的:(oracle,数据库,sql)