ORACLE:使用分隔符合并,但仅当两个操作数都不为空时

wkftcu5l  于 2022-10-04  发布在  Oracle
关注(0)|答案(4)|浏览(220)

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

因此,对于具有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个以上的列,并且您为它们指定了合理的名称,而不是a、b和c。;-)

我找不到一种更短、更容易或更易读的方法,但我想在完全放弃之前(或者自己浪费时间编写这样的函数),我应该在这里问问。

ukqbszuj

ukqbszuj1#

我知道你用的是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'));

或在实际的table上:

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;

现在我不确定这是否比您的原始示例更好(更具可读性):-)

5rgfhyps

5rgfhyps2#

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

rta7y2nd3#

AFAIK,没有简明的方法可以做到这一点。

在过去,我曾求助于

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

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

w9apscun

w9apscun4#

Not all fields will have data sequentially. This is for fields that are blank and without spaces:

  1. Evaluate if the field is blank, if so concatenate an empty field so it is ignored and if blank, concatenate the field with a space on the end.
  2. Then [TRIM] spaces (leading and trailing), then [REPLACE] spaces with your delimiter.

You can get creative with this until Oracle gives a function to do this.

Code snippet:

SELECT 
    f1,f2,f3,f4
  , REPLACE (TRIM(
     CASE WHEN f1 IS NULL THEN '' ELSE f1||' ' END||
     CASE WHEN f2 IS NULL THEN '' ELSE f2||' ' END||
     CASE WHEN f3 IS NULL THEN '' ELSE f3||' ' END||
     CASE WHEN f4 IS NULL THEN '' ELSE f4||' ' END),' ','|') concat_result
from 
    (SELECT 
         'I' f1
        ,'want' f2
        ,'' f3
        ,'concat' f4
 FROM dual) c'

相关问题