web-dev-qa-db-ja.com

複数の列を連結し、1つの列がnullの場合のスペース-Oracle

各値の間にスペースを入れて、複数の列を1つに連結する必要があります。問題は、1つの値がnullの場合、2つの値の間に2つのスペースができてしまうことです。

SELECT (FIRST_NAME || ' ' || MIDDLE_NAME || ' ' || LAST_NAME
  FROM TABLE_A;

ミドルネームがたまたまNULLの場合、姓と名の間に2つのスペースができてしまいます。これを回避し、null値がある場合にスペースを1つだけ持つ方法はありますか?

6
dstnrgrs

別のオプションは、デコードを使用することです:

SELECT decode(FIRST_NAME,'','',FIRST_NAME ||' ') ||
       decode(MIDDLE_NAME,'','',MIDDLE_NAME ||' ') || LAST_NAME
FROM TABLE_A;
0
SELECT TRIM(TRIM(FIRST_NAME || ' ' || MIDDLE_NAME) || ' ' || LAST_NAME)   
FROM TABLE_A; 
9
RedFilter

オラクルのドキュメントから:

CONCAT_WS(separator、str1、str2、...)

CONCAT_WS()は、Concatenate With Separatorの略で、CONCAT()の特殊な形式です。最初の引数は、残りの引数の区切り文字です。連結する文字列の間にセパレータが追加されます。区切り文字は、残りの引数と同様に文字列にすることができます。区切り文字がNULLの場合、結果はNULLになります。

そして非常に重要なコメント:

CONCAT_WS()は空の文字列をスキップしません。ただし、separator引数の後のNULL値はスキップされます。

したがって、あなたの場合は次のようになります。

CONCAT_WS(',', FIRST_NAME, MIDDLE_NAME, LAST_NAME);
5
omnomnom
with indata as
(
select 'John' as first_name, 'W' as middle_name, 'Smith ' as last_name from dual
union
select null as first_name, null as middle_name, 'Adams' as last_name from dual
union
select 'Tom' as first_name, null as middle_name, 'Jefferson' as last_name from dual
)
select
regexp_replace(trim(indata.first_name || ' ' || indata.middle_name || ' ' || indata.last_name), '\s{2,}', ' ')
from indata;
3
tbone

RPAD() を使用して、スペース文字を追加できます。

SELECT RPAD(first_name, LENGTH(first_name)+1, ' ')||RPAD(middle_name, LENGTH(middle_name)+1, ' ')||last_name
FROM TABLE_A;

RPADのパラメータのいずれかがNULLの場合、結果はNULLになり、Oracleでは文字列にNULLを追加すると、元の文字列が返されます。

1
ninesided

これは、通常、Oracleで複数のフィールドを連結し、空白を削除する方法です。

TRIM(REGEXP_REPLACE(HOUSE_NO || ' ' || PREFIX || ' ' || STREET_NAME || ' ' || STREET_TYPE || ' ' || SUFFIX, ' +', ' '))

  1. 必要なすべてのフィールドを、それぞれの間にスペースを入れて連結します。空の文字列とNULL値は、2つ以上のスペースになります。
  2. 正規表現を使用して、複数のスペース['+']の出現を単一のスペース['']に変更します。
  3. 最後に、結果の文字列の先頭または末尾、あるいはその両方の空白を削除します。
1
Erik Anderson

私は例を使ってこの回避策を持っています。お役に立てれば。 SQLサーバーに移動し、クエリに続いて新しいクエリとCPを選択します。

DECLARE @NULL_SAMLES TABLE
       (
       NS_ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED NOT NULL
      ,COL_01 VARCHAR(10) NULL
      ,COL_02 VARCHAR(10) NULL
      ,COL_03 VARCHAR(10) NULL
      ,COL_04 VARCHAR(10) NULL
   )

   INSERT INTO @NULL_SAMLES(COL_01,COL_02,COL_03,COL_04)
   VALUES
    ('A','B','C','D')
   ,(' ' ,'B','C','D')
   ,(' ',NULL,'C','D')
   ,('A','B',NULL,'D')
   ,('A','B','C',NULL)
   ,(NULL,'B',NULL,'D')
   ,(NULL,'B','C',NULL)
   ,('A',NULL,'C',NULL)
   ,('A',NULL,NULL,'D')
   ,('A',NULL,NULL,NULL)
   ,(NULL,'B',NULL,NULL)
   ,(NULL,NULL,'C',NULL)
   ,(NULL,NULL,NULL,'D')


   SELECT
        NS.COL_01
       ,NS.COL_02
       ,NS.COL_03
       ,NS.COL_04,
      Stuff(  
        Coalesce(', ' + nullif(NS.COL_01, ''), '') 
      + Coalesce(', ' + nullif(NS.COL_02, ''), '') 
      + Coalesce(', ' + nullif(NS.COL_03, ''), '') 
      +Coalesce(', ' + nullif(NS.COL_04, ''), '')
      , 1, 1, '') AS CONC_COLS
   FROM @NULL_SAMLES NS
0
Chetan Birajdar

連結できるCASEステートメントの単純な力を過小評価しないでください。そのまま実行できる自己完結型の例を次に示します。

SELECT
CASE WHEN x.FIRST_NAME IS NULL THEN x.FIRST_NAME ELSE x.FIRST_NAME || ' ' END || 
CASE WHEN x.MIDDLE_NAME IS NULL THEN x.MIDDLE_NAME ELSE x.MIDDLE_NAME  || ' ' END || 
x.LAST_NAME
FROM (SELECT 'John' AS FIRST_NAME, NULL AS MIDDLE_NAME, 'Doe' AS LAST_NAME FROM DUAL) x;
0
Gustavo Lopez

または、単にREPLACE関数を使用することもできます。

with indata as 
  (select 'John' as first_name, 'W' as middle_name, 'Smith ' as last_name from dual 
   union 
   select null as first_name, null as middle_name, 'Adams' as last_name from dual 
    union 
    select 'Tom' as first_name, null as middle_name, 'Jefferson' as last_name from dual) 
SELECT REPLACE(TRIM(indata.first_name || ' ' || indata.middle_name || ' ' || indata.last_name), '  ', ' ')
  FROM indata

(そして、サンプルデータの@tboneに感謝します:-)

さらに別のオプション:

SELECT first_name
       || DECODE(middle_name
          ,      NULL, NULL
          ,      ' ' || middle_name)
       || DECODE(last_name
          ,      NULL, NULL
          ,      ' ' || last_name) full_name
FROM   table_a
;
0
Tebbe