在PostgreSQL中使用CASE一次影响多个列
我有一个Postgres SELECT语句与这些表达式:
,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表达式来一键切换多列的输出?
1.标准SQL:LEFT JOIN单行值
您可以使用条件(从而评估一次),以 这种语法变体比较简单,速度更快,具有多个值 – 对于昂贵/冗长的条件特别有趣: 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由单行组成,无需进一步条件即可进行连接. 子查询中需要显式类型转换.我在示例中使用文本(这也是字符串文字的默认值).使用您的实际数据类型.语法快捷方式value :: type是Postgres特定的,对于标准SQL使用cast(值AS类型). 如果条件不为TRUE,x中的所有值都为NULL,并且COALESCE进入. 或者,由于所有候选值来自特定情况下的表rtd2,LEFT使用原始CASE条件加入rtd2,并将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 #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; 如果列不共享相同的数据类型,它会变得更复杂.您可以将它们全部转换为文本(并可选择在外部SELECT中转换),也可以… 2B.分解行类型 您可以使用自定义复合类型(行类型)来保存各种类型的值,并且只需将其扩展到外部SELECT.假设我们有三列:文本,整数和日期.要重复使用,请创建一个自定义复合类型: CREATE TYPE my_type (t1 text,t2 int,t3 date); 或者如果现有表的类型匹配,则可以使用表名称作为复合类型. 或者如果您只需要临时类型,您可以创建一个TEMPORARY TABLE,它在会话期间注册一个临时类型: CREATE TEMP TABLE my_type (t1 text,t3 date); 你甚至可以为一个单一的交易: CREATE TEMP TABLE my_type (t1 text,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',now()::date)::my_type ELSE (r2.team_name,r2.date_col)::my_type END).* FROM rtp JOIN rtd2 r2 ON <unknown condition>; CASE表达式通过这种方式对每一列进行一次评估.如果评估不是微不足道,另一个具有子查询的变体会更快. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |