在PostgreSQL中使用CASE一次影响多个列

前端之家收集整理的这篇文章主要介绍了在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单行值

您可以使用条件(从而评估一次),以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由单行组成,无需进一步条件即可进行连接.

查询中需要显式类型转换.我在示例中使用文本(这也是字符串文字的默认值).使用您的实际数据类型.语法快捷方式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表达式通过这种方式对每一列进行一次评估.如果评估不是微不足道,另一个具有子查询的变体会更快.

猜你在找的Postgre SQL相关文章