Ell*_* B. 26 sql postgresql 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
Run Code Online (Sandbox Code Playgroud)
在我的特定查询中有5个字段,其输出取决于是否rtp.team_id = rtp.sub_team_id计算为true.我CASE一遍又一遍地重复具有相同条件的陈述.
有没有什么方法可以组合这些CASE表达式来一次切换多列的输出?
Erw*_*ter 30
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;
Run Code Online (Sandbox Code Playgroud)
由于派生表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;
Run Code Online (Sandbox Code Playgroud)
它取决于连接条件和查询的其余部分.
如果各个列共享相同的数据类型,则可以在子查询中使用数组并在外部展开它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;
Run Code Online (Sandbox Code Playgroud)
如果列不共享相同的数据类型,则会变得更复杂.您可以将它们全部text转换为(并且可选地在外部转换回来SELECT),或者您可以......
您可以使用自定义复合类型(行类型)来保存各种类型的值,并在外部简单地*展开它SELECT.假设我们有三列:text,integer和date.要重复使用,请创建自定义复合类型:
CREATE TYPE my_type (t1 text, t2 int, t3 date);
Run Code Online (Sandbox Code Playgroud)
或者,如果现有表的类型匹配,则可以将表名用作复合类型.
或者,如果您只需要临时类型,则可以创建一个TEMPORARY TABLE,在会话期间注册临时类型:
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date);
Run Code Online (Sandbox Code Playgroud)
您甚至可以为单个事务执行此操作:
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date) ON COMMIT DROP;
Run Code Online (Sandbox Code Playgroud)
然后你可以使用这个查询:
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;
Run Code Online (Sandbox Code Playgroud)
或者甚至只是(与上面相同,更简单,更短,可能不太容易理解):
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>;
Run Code Online (Sandbox Code Playgroud)
在CASE每列这种方式表达被评估一次.如果评估不是微不足道的,那么带有子查询的另一个变体会更快.
| 归档时间: |
|
| 查看次数: |
93181 次 |
| 最近记录: |