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
, integer
và date
. Đố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.