8

我有一些TABLE1数据表:

+------------+
|    COL1    |
+------------+
|   FOO      |
|   BAR      |
|  (null)    |
|   EXP      |
+------------+

小提琴

当我执行:

SELECT listagg(col1, '#') within group(ORDER BY rownum) 
  FROM table1

我收到:FOO#BAR#EXP但我想拥有:FOO#BAR##EXP

LISTAGG忽略空单元格:/)

有什么想法可以在不编写自己的函数的情况下实现这一目标?

4

7 回答 7

8
select replace(listagg(NVL(col1, '#'), '#') 
within group(order by rownum),'###','##') from table1

你可以在NVL(col1, '#') 这里使用你可以传递任何值而不是null。

这是演示

于 2013-07-17T10:46:13.950 回答
6
select substr(listagg('#'||col1) within group (order by rownum),2)
from table1

在每个值之前添加分隔符(这只会为 NULL 生成分隔符),然后在没有分隔符的情况下聚合,并去除前导分隔符。

于 2014-08-05T09:45:49.037 回答
2

试试这个方法:

select replace(
                listagg(coalesce(col1,'replace'), '#') 
                within group(order by rownum),      
       'replace','') 
from table1

Sql 小提琴演示

于 2013-07-17T10:45:51.717 回答
1

另一种方法,使用模型子句

SQL> select rtrim(res, '#') as col1
  2    from ( select res
  3                , rn
  4             from table1
  5             model
  6             dimension by (rownum as rn)
  7             measures(cast(null as varchar2(500)) as res, col1)
  8             rules(
  9               res[any] order by rn desc= col1[cv()] || '#' || res[cv() + 1]
 10             )
 11          )
 12   where rn = 1
 13  /

COL1
--------------------
FOO#BAR##EXP

SQLFiddle 演示

于 2013-07-17T11:30:05.593 回答
1

请试试:

select replace(listagg(nvl(col1, '#') , '#') 
       within group(order by rownum), '##', '#') 
from table1
于 2013-07-17T11:00:41.037 回答
0

尝试这个

select 
  REPLACE(listagg(NVL(col1,' '), '#') within group(order by rownum),'# #','##') 
from table1

SQL 小提琴演示

于 2013-07-17T10:44:17.477 回答
0

恕我直言,值得一提的是,使用 usinglistagg时,您可能会遇到结果值的 4000 个字符的限制,然后寻求一些替代解决方案。解决方案是xmlagg,相比之下,它尊重 null值。因此考虑使用基于占位符的技巧listagg是否值得。

(我的情况正好相反:我需要忽略完全适合的空值,listagg但后来我达到了极限,被迫学习用xmlagg子句忽略值。这可以使用nvl2函数,但那是另一回事了。)

于 2021-01-19T12:29:52.390 回答