1. Standard-SQL:LEFT JOIN
един ред от стойности
Можете да LEFT JOIN
ред от стойности, използвайки условието (като по този начин го оценява веднъж). След това можете да добавите резервни стойности на колона с COALESCE()
.
Този вариант на синтаксис е по-кратък и малко по-бърз с множество стойности - особено интересен за скъпо/продължително условие:
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;
Тъй като получената таблица x
се състои от единичен ред, присъединяването без допълнителни условия е добре.
Явни преобразувания на типове са необходими в подзаявката. Използвам text
в примера (което така или иначе е по подразбиране за низови литерали). Използвайте действителните си типове данни. Синтаксисът за бърз достъп value::type
е специфичен за Postgres, използвайте cast(value AS type)
за стандартен SQL.
Ако условието не е TRUE
, всички стойности в x
са NULL и COALESCE
влиза.
Или , тъй като всички кандидат стойности идват от таблица rtd2
във вашия конкретен случай, LEFT JOIN
към rtd2
използвайки оригиналния CASE
условие и CROSS JOIN
към ред със стойности по подразбиране:
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;
Зависи от условията за присъединяване и останалата част от заявката.
2. Специфично за PostgreSQL
2a. Разгъване на масив
Ако различните ви колони споделят един и същи тип данни , можете да използвате масив в подзаявка и да го разширите във външния SELECT
:
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;
Става по-сложно, ако колоните не споделят един и същи тип данни. Можете или да ги прехвърлите всички към text
(и по желание конвертирайте обратно във външния SELECT
), или можете ...
2б. Декомпозиране на тип ред
Можете да използвате персонализиран съставен тип (тип ред), за да съхранявате стойности от различни типове и просто *-да го разширите във външния SELECT
. Да кажем, че имаме три колони:text
, integer
и date
. За повторени използвайте, създайте персонализиран съставен тип:
CREATE TYPE my_type (t1 text, t2 int, t3 date);
Или ако типът на съществуваща таблица съвпада, можете просто да използвате името на таблицата като съставен тип.
Или ако имате нужда само от типа временно , можете да създадете TEMPORARY TABLE
, който регистрира временен тип за продължителността на вашата сесия :
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date);
Можете дори да направите това за една транзакция :
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date) ON COMMIT DROP;
Тогава можете да използвате тази заявка:
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;
Или дори просто (същото като по-горе, по-просто, по-кратко, може би не толкова лесно за разбиране):
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
изразът се оценява веднъж за всяка колона по този начин. Ако оценката не е тривиална, другият вариант с подзаявка ще бъде по-бърз.