web-dev-qa-db-ja.com

PostgreSQLの条件付き文字列連結

現在、_owner_addr1_、_owner_addr2_、_owner_addr3_列を含むテーブルparcelsがあります。場合によっては、後者の2つのフィールドの一方または両方が空になります。これらを単一の新しいフィールド_owner_addr_に結合したいと思います。ここで、上記の各フィールドは、それらの間の_//_と連結されます。

しかし、元の列の1つ以上がNULLの場合、_//_を結果列に連結したくありません。したがって、たとえば、_owner_addr1_が_123 4th Avenue SE_であり、_owner_addr2_および_owner_addr3_がNULLである場合、結果列は_123 4th Avenue SE_ではなく_123 4th Avenue SE // //_にする必要があります)__(NULL文字列の間に_//_を付けてCONCAT()を実行した場合に発生します...非NULL列の間に_//_を追加するか、省略しますNULL以外の列が1つしかない場合は完全に一致します。

空の行を除外するPostgresqlでこのような条件付き連結を行う簡単な方法はありますか?それとも、pythonスクリプトを書いてこれを行うべきですか?

7
J. Taylor

関数 concat_ws() は、望みどおりの動作をします。最初のパラメーターは、残りの部分の間の接着剤として使用されます。ヌルは無視されます:

select concat_ws('//', owner_addr1, owner_addr2, owner_addr3)

テスト:

red=# select concat_ws('//', 'abc', null, null, 'xx', null, 'xyz', null) 
          as address;
   address    
--------------
 abc//xx//xyz
(1 row)
13
ypercubeᵀᴹ

CASEステートメントを使用することはおそらく最も明白です。 4つのケースがあります。

owner_addr2 IS NULL AND owner_addr3 IS NULL => ''       
owner_addr2 IS NULL AND owner_addr3 IS NOT NULL => '//' || owner_addr3
owner_addr2 IS NOT NULL AND owner_addr3 IS NULL => '//' || owner_addr2
owner_addr2 IS NOT NULL AND owner_addr3 IS NOT NULL '//' || owner_addr2 || '//' owner_addr3

SELECT owner_addr1 
    || CASE WHEN owner_addr2 IS NULL AND owner_addr3 IS NULL
            THEN ''
            WHEN owner_addr2 IS NULL AND owner_addr3 IS NOT NULL
            THEN '//' || owner_addr3
            WHEN owner_addr2 IS NOT NULL AND owner_addr3 IS NULL 
            THEN '//' || owner_addr2   
            WHEN owner_addr2 IS NOT NULL AND owner_addr3 IS NOT NULL 
            THEN '//' || owner_addr2 || '//' || owner_addr3
       END AS owner_addr
FROM ...

別の方法は、2つのCASEステートメントを使用することです。

SELECT owner_addr1 
    || CASE WHEN owner_addr2 IS NULL 
            THEN '' 
            ELSE '//' || owner_addr2
       END
    || CASE WHEN owner_addr3 IS NULL 
            THEN '' 
            ELSE '//' || owner_addr3
       END as owner_addr
FROM ...

COALESCEはCASEの代わりに使用できます。

SELECT owner_addr1 
    || COALESCE('//' || owner_addr2, '')
    || COALESCE('//' || owner_addr3, '') as owner_addr
FROM ...
2
Lennart