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。分解行类型
您可以使用自定义复合类型(行类型)来保存各种类型的值,并简单地将其 *-expand 到 external 中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
方式对每一列计算一次表达式。如果评估不是微不足道的,那么带有子查询的另一个变体会更快。