web-dev-qa-db-fra.com

Concaténation conditionnelle de chaînes dans PostgreSQL

J'ai une table parcels qui contient actuellement les colonnes owner_addr1, owner_addr2, owner_addr3. Parfois, l'un des deux derniers champs ou les deux sont vides. Je veux les combiner en un seul nouveau champ, owner_addr Où chacun des champs ci-dessus est concaténé avec // Entre chacun d'eux.

Mais si une ou plusieurs des colonnes d'origine sont NULL, je ne veux pas concaténer // À la colonne de résultat. Ainsi, par exemple, si owner_addr1 Est 123 4th Avenue SE Et owner_addr2 Et owner_addr3 Sont NULL, alors je veux que la colonne de résultat soit simplement 123 4th Avenue SE, Pas 123 4th Avenue SE // // (Ce qui arriverait si je faisais simplement CONCAT() avec // Entre les chaînes NULL ... Je veux seulement ajouter // Entre les colonnes nonNULL, ou laissez-le complètement s'il n'y a qu'une seule colonne nonNULL.

Existe-t-il un moyen facile de faire ce type de concaténation conditionnelle dans Postgresql, où il laisse de côté les lignes vides? Ou dois-je écrire un script python pour ce faire?

7
J. Taylor

La fonction concat_ws() fait exactement ce que vous voulez. Le premier paramètre est utilisé comme colle entre les autres. Les valeurs nulles sont ignorées:

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

Tester:

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

Il est probablement plus évident d'utiliser une instruction CASE. Il y a 4 cas:

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 ...

Une alternative consiste à utiliser 2 instructions 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 peut être utilisé à la place de CASE:

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