问题描述
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
,则inx
中的所有值都为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
表达式一次,每列这样评价。如果求值不平凡,则带有子查询的其他变体将更快。
解决方法
我有一个SELECT
带有这些表达式的Postgres语句:
,CASE WHEN (rtp.team_id = rtp.sub_team_id)
THEN 'testing'
ELSE TRIM(rtd2.team_name)
END AS testing_testing,CASE WHEN (rtp.team_id = rtp.sub_team_id)
THEN 'test example'
ELSE TRIM(rtd2.normal_data)
END AS test_response,CASE WHEN (rtp.team_id = rtp.sub_team_id)
THEN 'test example #2'
ELSE TRIM(rtd2.normal_data_2)
END AS another_example
在我的特定查询中,有5个字段,其输出取决于是否rtp.team_id =
rtp.sub_team_id
评估为true。我CASE
一遍又一遍地重复具有相同条件的语句。
有什么方法可以组合这些CASE
表达式来一次切换多个列的输出?