Nối chuỗi có điều kiện trong PostgreSQL


7

Tôi có một bảng parcelshiện có chứa các cột owner_addr1, owner_addr2, owner_addr3. Đôi khi, một hoặc cả hai trường sau đều trống. Tôi muốn kết hợp chúng vào một trường mới, owner_addrtrong đó mỗi trường ở trên được nối với //nhau giữa mỗi trường.

Nhưng nếu một hoặc nhiều cột ban đầu là NULL, tôi không muốn nối //với cột kết quả. Vì vậy, ví dụ, nếu owner_addr1123 4th Avenue SEowner_addr2owner_addr3NULL, sau đó tôi muốn cột kết quả chỉ có 123 4th Avenue SE, không 123 4th Avenue SE // //(mà sẽ xảy ra nếu tôi chỉ làm CONCAT()với //giữa chuỗi NULL ... Tôi chỉ muốn thêm //giữa phi NULLcột, hoặc từ bỏ nó hoàn toàn nếu chỉ có một NULLcột không .

Có một cách dễ dàng để thực hiện kiểu ghép nối có điều kiện này trong Postgresql, nơi nó để lại các dòng trống? Hay tôi nên viết một kịch bản python để làm điều này?


1
Câu trả lời liên quan có thể giúp ích: stackoverflow.com/q/12310986/939860 . Lưu ý phần cuối cùng về concat_ws()(và concat()) có biến động chức năng STABLE(không IMMUTABLE), cấm sử dụng trực tiếp chúng trong các chỉ mục biểu thức.
Erwin Brandstetter

Câu trả lời:


13

Các chức năng concat_ws()làm chính xác những gì bạn muốn. Tham số đầu tiên được sử dụng làm keo giữa phần còn lại. Nulls bị bỏ qua:

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

Kiểm tra:

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

2

Có lẽ rõ ràng nhất để sử dụng một tuyên bố CASE. Có 4 trường hợp:

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

Một cách khác là sử dụng 2 câu lệnh 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 có thể được sử dụng thay vì CASE:

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

Lưu ý rằng câu trả lời giả định rằng owner_addr1nó không phải là null (câu hỏi dường như ngụ ý điều đó, vì vậy nó sẽ ổn).
ypercubeᵀᴹ

1
Vâng, tôi cho rằng. Trở nên phức tạp hơn nếu đó không phải là trường hợp. CONCAT_WS trông giống như một chức năng gọn gàng, làm tôi nhớ đến LISP :-)
Lennart

1
hình thức kết hợp có thể được sử dụng ba thuật ngữ giống nhau và sau đó là một chuỗi con cắt nhỏ bắt đầu
Jasen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.