如何使用Oracle的LISTAGG功能和独特的过滤器?

时间:2011-09-08 22:05:26

标签: oracle group-by oracle11g aggregate-functions

我有一张这样的表:

group_id  name  
--------  ----
1         David
1         John
1         Alan
1         David
2         Julie
2         Charles

我想要以下结果:

group_id  names
--------  -----
1         'Alan, David, John'
2         'Charles, Julie'

我可以使用以下查询:

select group_id, 
       listagg(name, ',') within group (order by name) as names
from demotable
group by group_id 

得到这个(非常相似的结果):

group_id  names
--------  -----
1         'Alan, David, David, John'
2         'Charles, Julie'

如何根据LISTAGG来电中的唯一性来过滤名称?

7 个答案:

答案 0 :(得分:45)

我今天没有11g实例,但你不能使用:

SELECT group_id,
       LISTAGG(name, ',') WITHIN GROUP (ORDER BY name) AS names
  FROM (
       SELECT UNIQUE
              group_id,
              name
         FROM demotable
       )
 GROUP BY group_id

答案 1 :(得分:16)

超级简单的答案 - 解决了!

select group_id, 
regexp_replace(
    listagg(name, ',') within group (order by name)
    ,'([^,]+)(,\1)*(,|$)', '\1\3')
from demotable
group by group_id;  

这仅适用于您将分隔符指定为','不是','即 逗号后只能用于空格。如果您想在逗号后面加上空格 - 这是一个示例。

select 
replace(
    regexp_replace(
     regexp_replace('BBall, BBall, BBall, Football, Ice Hockey ',',\s*',',')            
    ,'([^,]+)(,\1)*(,|$)', '\1\3')
,',',', ') 
from dual

给出 BBall,足球,冰球

我的完整答案here

答案 2 :(得分:5)

create table demotable(group_id number, name varchar2(100));
insert into demotable values(1,'David');
insert into demotable values(1,'John');
insert into demotable values(1,'Alan');
insert into demotable values(1,'David');
insert into demotable values(2,'Julie');
insert into demotable values(2,'Charles');
commit;

select group_id, 
       (select listagg(column_value, ',') within group (order by column_value) from table(coll_names)) as names
from (
  select group_id, collect(distinct name) as coll_names 
    from demotable
    group by group_id 
)

GROUP_ID    NAMES
1   Alan,David,John
2   Charles,Julie

答案 3 :(得分:2)

select group_id, 
       listagg(name, ',') within group (order by name) as names
       over (partition by group_id)   
from demotable
group by group_id 

答案 4 :(得分:0)

在基于最外层查询的聚合之前,我需要将这段代码作为带有一些数据过滤器的子查询,但我无法使用所选答案代码执行此操作,因为此过滤器应该位于最内部选择(第三级查询)和过滤器参数在最外面的选择(第一级查询),这给了我错误 ORA-00904:" TB_OUTERMOST"。" COL" :无效标识符,因为ANSI SQL声明表引用(相关名称)的范围仅限于一个级别。

我需要一个没有子查询级别的解决方案,下面这个对我来说很有用:

with

demotable as
(
  select 1 group_id, 'David'   name from dual union all
  select 1 group_id, 'John'    name from dual union all
  select 1 group_id, 'Alan'    name from dual union all
  select 1 group_id, 'David'   name from dual union all
  select 2 group_id, 'Julie'   name from dual union all
  select 2 group_id, 'Charlie' name from dual
)

select distinct 
  group_id, 
  listagg(name, ',') within group (order by name) over (partition by group_id) names
from demotable
-- where any filter I want
group by group_id, name
order by group_id;

答案 5 :(得分:0)

下面的

没有记录,oracle也不推荐。 并且无法在功能中应用,显示错误

select wm_concat(distinct name) as names from demotable group by group_id

问候 齐亚

答案 6 :(得分:-1)

在11g中你可以像这样使用未记录的函数wm_concat:

     select wm_concat(distinct name) as names from demotable group by group_id