PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Sử dụng CASE trong PostgreSQL để ảnh hưởng đến nhiều cột cùng một lúc

1. Standard-SQL:LEFT JOIN một hàng giá trị duy nhất

Bạn có thể LEFT JOIN một hàng giá trị sử dụng điều kiện (do đó đánh giá nó một lần). Sau đó, bạn có thể thêm giá trị dự phòng cho mỗi cột bằng COALESCE() .

Biến thể cú pháp này ngắn hơn và nhanh hơn một chút với nhiều giá trị - đặc biệt thú vị đối với điều kiện đắt / dài:

SELECT COALESCE(x.txt1, trim(r2.team_name))     AS testing_testing
     , COALESCE(x.txt2, trim(r2.normal_data))   AS test_response
     , COALESCE(x.txt3, trim(r2.normal_data_2)) AS another_example
FROM   rtp
JOIN   rtd2 r2 ON <unknown condition> -- missing context in question
LEFT   JOIN (
   SELECT 'testing'::text         AS txt1
        , 'test example'::text    AS txt2
        , 'test example #2'::text AS txt3
   ) x ON rtp.team_id = rtp.sub_team_id;

Kể từ bảng dẫn xuất x bao gồm một đơn hàng, tham gia mà không cần thêm điều kiện cũng được.

Phôi loại rõ ràng cần thiết trong truy vấn con. Tôi sử dụng text trong ví dụ (dù sao cũng là mặc định cho các ký tự chuỗi). Sử dụng các loại dữ liệu thực tế của bạn. Phím tắt cú pháp value::type là dành riêng cho Postgres, sử dụng cast(value AS type) cho SQL chuẩn.

Nếu điều kiện không phải là TRUE , tất cả các giá trị trong x là NULL và COALESCE đá vào.

Hoặc , vì tất cả các giá trị ứng viên đến từ bảng rtd2 trong trường hợp cụ thể của bạn, LEFT JOIN thành rtd2 sử dụng CASE gốc điều kiện và CROSS JOIN thành một hàng có giá trị mặc định:

SELECT COALESCE(trim(r2.team_name),     x.txt1) AS testing_testing
     , COALESCE(trim(r2.normal_data),   x.txt2) AS test_response
     , COALESCE(trim(r2.normal_data_2), x.txt3) AS another_example
FROM   rtp
LEFT   JOIN rtd2 r2 ON <unknown condition>  -- missing context in question
                   AND rtp.team_id = rtp.sub_team_id
CROSS  JOIN (
   SELECT 'testing'::text         AS txt1
        , 'test example'::text    AS txt2
        , 'test example #2'::text AS txt3
   ) x;

Nó phụ thuộc vào các điều kiện kết hợp và phần còn lại của truy vấn.

2. PostgreSQL cụ thể

2a. Mở rộng một mảng

Nếu các cột khác nhau của bạn chia sẻ cùng một loại dữ liệu , bạn có thể sử dụng một mảng trong một truy vấn con và mở rộng nó trong SELECT bên ngoài :

SELECT x.combo[1], x.combo[2], x.combo[3]
FROM  (
   SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
            THEN '{test1,test2,test3}'::text[]
            ELSE ARRAY[trim(r2.team_name)
                     , trim(r2.normal_data)
                     , trim(r2.normal_data_2)]
          END AS combo
   FROM   rtp
   JOIN   rtd2 r2 ON <unknown condition>
   ) x;

Nó sẽ phức tạp hơn nếu các cột không chia sẻ cùng một kiểu dữ liệu. Bạn có thể truyền tất cả chúng thành text (và tùy chọn chuyển đổi trở lại trong SELECT bên ngoài ), hoặc bạn có thể ...

2b. Phân rã một loại hàng

Bạn có thể sử dụng loại kết hợp tùy chỉnh (loại hàng) để chứa các giá trị thuộc nhiều loại khác nhau và chỉ cần *-mở rộng nó trong SELECT bên ngoài . Giả sử chúng ta có ba cột:text , integerdate . Đối với lặp lại sử dụng, tạo một loại kết hợp tùy chỉnh:

CREATE TYPE my_type (t1 text, t2 int, t3 date);

Hoặc nếu loại bảng hiện có khớp, bạn chỉ có thể sử dụng tên bảng làm loại kết hợp.

Hoặc nếu bạn chỉ cần loại tạm thời , bạn có thể tạo TEMPORARY TABLE , đăng ký một loại tạm thời trong suốt phiên của bạn :

CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date);

Bạn thậm chí có thể làm điều này cho một giao dịch duy nhất :

CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date) ON COMMIT DROP;

Sau đó, bạn có thể sử dụng truy vấn này:

SELECT (x.combo).*  -- parenthesis required
FROM  (
   SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
             THEN ('test', 3, now()::date)::my_type  -- example values
             ELSE (r2.team_name
                 , r2.int_col
                 , r2.date_col)::my_type
          END AS combo
   FROM   rtp
   JOIN   rtd2 r2 ON <unknown condition>
   ) x;

Hoặc thậm chí chỉ (giống như trên, đơn giản hơn, ngắn hơn, có thể ít dễ hiểu hơn):

SELECT (CASE WHEN rtp.team_id = rtp.sub_team_id
           THEN ('test', 3, now()::date)::my_type
           ELSE (r2.team_name, r2.int_col, r2.date_col)::my_type
        END).*
FROM   rtp
JOIN   rtd2 r2 ON <unknown condition>;

CASE biểu thức được đánh giá một lần cho mỗi cột theo cách này. Nếu đánh giá không nhỏ, biến thể khác có truy vấn con sẽ nhanh hơn.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Khóa nào, nếu có, có sử dụng 'CREATE TRIGGER' trong PostgreSQL 9.4.2 không

  2. Làm thế nào chính xác làm việc vòng chức năng trong postgresql?

  3. Django OneToOneField với trường trống có thể có

  4. Cách gắn khối lượng postgresql bằng Aws EBS trong Kubernete

  5. Nhập tệp CSV đã nén vào PostgreSQL