带有 rep substr 函数的 Listagg 函数

Listagg function with rep substr function

原始数据:

Col1    Col2    Col3    Col4
Ajay    G1  B1  10.201.131.27
Ajay    G1  B2  10.201.131.27
Ajay    G1  B1  10.201.131.28
Ajay    G1  B2  10.201.131.28
Ajay    G1  B1  10.201.131.29
Ajay    G1  B2  10.201.131.29

使用 Oracle 10g 的预期输出

Col1    Col2    Col3    Col4
Ajay    G1  B1,B2   10.201.131.27,10.201.131.28, 10.201.131.29

如果有人能够提供帮助,将非常高兴。

我使用的查询:

select * from (select 
Col1,
Col2,
substr(regexp_replace(','||(LISTAGG(( CASE WHEN T1.COl3 IS NULL OR TRIM( T1.COl3 ) ='' THEN NULL ELSE T1.COl3   END), ',') WITHIN GROUP (ORDER BY T1.COl1 )), '(,[^,]+)()+', ''),2) as COl3 ,
substr(regexp_replace(','||(LISTAGG(( CASE WHEN T1.COl4 IS NULL OR TRIM( T1.COl4 ) ='' THEN NULL ELSE  T1.COl4   END), ',') WITHIN GROUP (ORDER BY T1.COl1 )), '(,[^,]+)()+', ''),2) as COl4 ,
from T1
Group by 
Col1
)abc

我得到的输出如下,

Col1    Col2    Col3    Col4
Ajay    G1  B1,B2   10.201.131.27
Ajay    G1  B1,B2   10.201.131.28
Ajay    G1  B1,B2   10.201.131.29

提前致谢。

with t (Col1,    Col2,    Col3,    Col4) as (
select 'Ajay',    'G1',  'B1',  '10.201.131.27' from dual union all
select 'Ajay',    'G1',  'B2',  '10.201.131.27' from dual union all
select 'Ajay',    'G1',  'B1',  '10.201.131.28' from dual union all
select 'Ajay',    'G1',  'B2',  '10.201.131.28' from dual union all
select 'Ajay',    'G1',  'B1',  '10.201.131.29' from dual union all
select 'Ajay',    'G1',  'B2',  '10.201.131.29' from dual)
, t1 as (
select Col1, Col2
, listagg(Col3, ',') within group (order by Col3) x
, listagg(Col4, ',') within group (order by Col4) y
from t
group by Col1, Col2
)
select Col1, Col2
, rtrim(regexp_replace(x || ',', '([^,]+,)+', ''), ',') Col3_
, rtrim(regexp_replace(y || ',', '([^,]+,)+', ''), ',') Col4_
from t1
;

COL1  CO  COL3_                           COL4_                                                       
----  --  ------------------------------  ------------------------------------------------------------
Ajay  G1  B1,B2                           10.201.131.27,10.201.131.28,10.201.131.29                     

我分两步显示,但也可以一步显示。

select Col1, Col2
, rtrim(regexp_replace(listagg(Col3, ',') within group (order by Col3) || ',', '([^,]+,)+', ''), ',') Col3_
, rtrim(regexp_replace(listagg(Col4, ',') within group (order by Col4) || ',', '([^,]+,)+', ''), ',') Col4_
from t
group by Col1, Col2
;

要消除 LISTAGG 中的重复,您可以在 Oracle 10 中使用 row_number 函数来定义 重复的顺序

在下一步中,您只传递给 LISTAGG 函数 first duplicated (row_number = 1),所有更高的重复项都重置为 NULLLISTAGG.

忽略

此处查询

with t2 as (
select 
COL1, COL2,
COL3,
row_number() over (partition by col1, col2, col3 order by null) as rn3,
COL4,
row_number() over (partition by col1, col2, col4 order by null) as rn4
from t)
select
  COL1, COL2,
  listagg(case when rn3 = 1 then COL3 end,',') within group (order by COL3) COL3,
  listagg(case when rn4 = 1 then COL4 end,',') within group (order by COL4) COL4
from t2
group by COL1, COL2

结果

COL1,   COL2, COL3, COL4
Ajay    G1  B1,B2   10.201.131.27,10.201.131.28,10.201.131.29

请注意,这种方法比使用 REGEXP 进行的后续消除要好得多,因为在开始消除之前,您经常遇到 ORA-01489: result of string concatenation is too long 的非平凡数据.

另请注意,您可以升级到 Oracle 19(从 Oracle 10 的角度可以认为它已过期)并且您可以使用具有相同影响的功能 LISTAGG (DISTINCT 而无需消除重复项。此版本还优雅地处理了 owerflow 问题。