Ответ 1
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
), либо вы можете...
2b. Разделить тип строки
Вы можете использовать собственный составной тип (тип строки) для хранения значений различных типов и просто * -расширить его во внешнем 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
оценивается один раз для каждого столбца таким образом. Если оценка не является тривиальной, другой вариант с подзапросом будет быстрее.