甲骨文:Concat的与分隔符,但只有两个操作数都是NOT NULL(Oracle: Concat

2019-06-26 06:20发布

我要选择几个字段的串联,但它们之间的隔板。 该分离器只应出现在两个操作数不为空。

因此,对于一个创纪录的a='foo', b=NULL, c='bar' ,我想要得到的结果abc='foo;bar' (不是'foo;;bar' )。

我想有这样一个功能concat_sep(a, b, ';')只增加了“;” 其间,如果a和b不为空。

当然,我可以使用NVL2这样的:

select
  a, b, c, 
  substr(abc, 1, length(abc) - 1) as abc
from
  (select
    a, b, c, 
    nvl2(a, a || ';', '') || nvl2(b, b || ';', '') || nvl2(c, c || ';', '') as abc
  from
    Table1)

但正如你所看到的,这个代码很快就成为妨碍,尤其是当你有超过3列,你已经给了他们合理的名称,而不是一个,b和c。 ;-)

我找不到更短,更容易或更可读的方式,但我认为我会问这里放弃完全(或浪费时间写这样的功能我)了。

Answer 1:

我知道你正在使用10g中,这样就不会工作。 但对于完整性, LISTAGG()处理NULL “正确”的价值观。 对于你必须更新到11g2,虽然:

-- Some sample data, roughly equivalent to yours
with t as (
  select 'foo' as x from dual union all
  select null       from dual union all
  select 'bar'      from dual
)
-- Use the listagg aggregate function to join all values
select listagg(x, ';') within group (order by rownum)
from t;

还是有点更简洁,如果要列出一个表列:

-- I use SYS.ORA_MINING_VARCHAR2_NT as a TABLE TYPE. Use your own, if you prefer
select listagg(column_value, ';') within group (order by rownum)
from table(ORA_MINING_VARCHAR2_NT('foo', null, 'bar'));

或针对实际的表:

select listagg(column_value, ';') 
       within group (order by rownum)
from Table1
cross join table(ORA_MINING_VARCHAR2_NT(Table1.a, Table1.b, Table1.c))
group by Table1.id;

现在,我不知道这是不是你原来的例子好多了(更易读):-)



Answer 2:

据我所知,有这样做没有简洁的方式。

在过去,我已经使出

SELECT a
||     DECODE(b
       ,      NULL, NULL
       ,      ';' || b)
||     DECODE(c
       ,      NULL, NULL
       ,      ';' || c)
||     DECODE(d
       ,      NULL, NULL
       ,      ';' || d)
...
FROM   table1

但是这并不比你的好例子。



Answer 3:

select trim(';' from REGEXP_REPLACE (a || ';' || b || ';' || c , ';+' , ';')) abc 
from Table1


文章来源: Oracle: Concat with delimiter, but only if both operands are NOT NULL