Oracle:具有分隔符的Concat,但仅当两个操作数都为NOT NULL时才会出现

Gol*_*rol 9 oracle concat oracle10g

我想选择几个字段的串联,但在它们之间有一个分隔符.只有当两个操作数都不为空时,分隔符才应该存在.

所以对于一个记录a='foo', b=NULL, c='bar',我想得到结果abc='foo;bar'(不是'foo;;bar').

我希望有一个像concat_sep(a, b, ';')这样的函数只添加'​​;' 如果a和b都不为空,则为inbetween.

当然,我可以像这样使用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)
Run Code Online (Sandbox Code Playgroud)

但是正如你所看到的,这段代码很快就会变得很无聊,特别是当你有超过3列的时候,你已经给了它们合理的名字,而不是a,b和c.;-)

我找不到更短,更容易或更易阅读的方式,但我想在完全放弃之前我会问这里(或者浪费时间自己写这样的功能).

Luk*_*der 6

我知道你使用的是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;
Run Code Online (Sandbox Code Playgroud)

或者更简洁一点,如果你想列出表中的列:

-- 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'));
Run Code Online (Sandbox Code Playgroud)

或者针对实际的表格:

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;
Run Code Online (Sandbox Code Playgroud)

现在我不确定这是否比原始示例更好(更易读):-)

  • 也行不通.显然我还没有在我的数据库中获得数据挖掘功能.我会牢记这一点,但我觉得我不应该在生产代码中使用这个解决方案.;-) (2认同)

Edo*_*rdo 5

select trim(';' from REGEXP_REPLACE (a || ';' || b || ';' || c , ';+' , ';')) abc 
from Table1
Run Code Online (Sandbox Code Playgroud)

  • 嘿,欢迎来到 SO,最好详细说明您的答案:https://stackoverflow.com/help/how-to-answer (2认同)