programing

Oracle: 구분 기호와 일치하지만 두 피연산자가 모두 NULL이 아닌 경우에만 해당

sourcetip 2023. 7. 31. 22:19
반응형

Oracle: 구분 기호와 일치하지만 두 피연산자가 모두 NULL이 아닌 경우에만 해당

두 필드 사이에 구분 기호가 있는 연결을 선택합니다.두 피연산자가 모두 null이 아닌 경우에만 구분 기호가 있어야 합니다.

그래서 기록을 위해.a='foo', b=NULL, c='bar'나는 결과를 얻고 싶습니다.abc='foo;bar'(아닙니다.'foo;;bar').

저는 다음과 같은 기능을 갖고 싶습니다.concat_sep(a, b, ';')a와 b가 모두 null이 아닌 경우에만 중간에 ';'를 추가합니다.

물론 다음과 같이 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 대신에 적절한 이름을 지정하면 더욱 그렇습니다. ;-)

저는 더 짧고, 더 쉬우며, 더 읽기 쉬운 방법을 찾을 수 없었지만, 완전히 포기하기 전에 여기서 물어보려고 생각했습니다(또는 그런 기능을 직접 작성하는 데 시간을 낭비했습니다).

저는 당신이 10g을 사용하고 있다는 것을 알고 있기 때문에, 그것은 작동하지 않을 것입니다.하지만 완성도를 위해 손잡이는NULL값 "sigma"입니다.이를 위해서는 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;

이제 저는 이것이 당신의 원래 예시보다 훨씬 더 나은(더 읽기 쉬운) 것인지 확신할 수 없습니다 :-)

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

AFAIK, 이것을 하는 간단한 방법은 없습니다.

과거에, 저는 도움을 했습니다.

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

하지만 그것은 당신의 예보다 나을 것이 없습니다.

모든 필드에 순차적으로 데이터가 있는 것은 아닙니다.이것은 공백이 없고 공백이 없는 필드에 대한 것입니다.

  1. 필드가 비어 있는지 여부를 평가하고, 필드가 비어 있으면 필드를 무시하도록 연결하고, 비어 있으면 필드 끝에 공백을 연결합니다.

  2. 그런 다음 [TRIM] 공백(선행 및 후행), [REPLACE] 공백을 구분 기호로 바꿉니다.

Oracle이 이를 위한 기능을 제공할 때까지 이를 통해 창의적인 작업을 수행할 수 있습니다.

코드 조각:

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'

언급URL : https://stackoverflow.com/questions/11454136/oracle-concat-with-delimiter-but-only-if-both-operands-are-not-null

반응형