Oracle 11g:LISTAGG忽略NULL值

时间:2013-07-17 10:35:03

标签: sql plsql oracle11g

我有一些表TABLE1包含数据:

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

FIDDLE

执行时:

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

我收到:FOO#BAR#EXP但我希望:FOO#BAR##EXP

LISTAGG忽略空单元格:/)

没有编写自己的函数就能实现这个目标吗?

7 个答案:

答案 0 :(得分:4)

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

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

HErE is the demo

答案 1 :(得分:2)

select substr(listagg('#'||col1) within group (order by rownum),2)
from table1

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

答案 2 :(得分:1)

另一种方法,使用model clause

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 Demo

答案 3 :(得分:0)

试试这个

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

SQL FIDDLE DEMO

答案 4 :(得分:0)

尝试这种方式:

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

Sql Fiddle Demo

答案 5 :(得分:0)

请尝试:

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

答案 6 :(得分:0)

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

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