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

前端之家收集整理的这篇文章主要介绍了在PostgreSQL中使用CASE一次影响多个列前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个Postgres SELECT语句与这些表达式:
  1. ,CASE WHEN (rtp.team_id = rtp.sub_team_id)
  2. THEN 'testing'
  3. ELSE TRIM(rtd2.team_name)
  4. END AS testing_testing,CASE WHEN (rtp.team_id = rtp.sub_team_id)
  5. THEN 'test example'
  6. ELSE TRIM(rtd2.normal_data)
  7. END AS test_response,CASE WHEN (rtp.team_id = rtp.sub_team_id)
  8. THEN 'test example #2'
  9. ELSE TRIM(rtd2.normal_data_2)
  10. END AS another_example

在我特别的查询中有5个字段,其输出取决于rtp.team_id = rtp.sub_team_id的值是否为true.我一遍又一遍地重复相同条件的CASE语句.

有没有什么办法可以组合这些CASE表达式来一键切换多列的输出

1.标准sql:LEFT JOIN单行值

您可以使用条件(从而评估一次),以LEFT JOIN的一行值.然后,您可以使用COALESCE()为每列添加后备值.

这种语法变体比较简单,速度更快,具有多个值 – 对于昂贵/冗长的条件特别有趣:

  1. 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
  2. FROM rtp
  3. JOIN rtd2 r2 ON <unknown condition> -- missing context in question
  4. LEFT JOIN (
  5. SELECT 'testing'::text AS txt1,'test example'::text AS txt2,'test example #2'::text AS txt3
  6. ) 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加入到具有默认值的行中:

  1. 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
  2. FROM rtp
  3. LEFT JOIN rtd2 r2 ON <unknown condition> -- missing context in question
  4. AND rtp.team_id = rtp.sub_team_id
  5. CROSS JOIN (
  6. SELECT 'testing'::text AS txt1,'test example #2'::text AS txt3
  7. ) x;

这取决于连接条件和查询的其余部分.

2. Postgresql特定的

2A.展开数组

如果您的各种列共享相同的数据类型,则可以在子查询中使用数组,并在外部SELECT中展开它:

  1. SELECT x.combo[1],x.combo[2],x.combo[3]
  2. FROM (
  3. SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
  4. THEN '{test1,test2,test3}'::text[]
  5. ELSE ARRAY[trim(r2.team_name),trim(r2.normal_data),trim(r2.normal_data_2)]
  6. END AS combo
  7. FROM rtp
  8. JOIN rtd2 r2 ON <unknown condition>
  9. ) x;

如果列不共享相同的数据类型,它会变得更复杂.您可以将它们全部转换为文本(并可选择在外部SELECT中转换),也可以…

2B.分解行类型

您可以使用自定义复合类型(行类型)来保存各种类型的值,并且只需将其扩展到外部SELECT.假设我们有三列:文本,整数和日期.要重复使用,请创建一个自定义复合类型:

  1. CREATE TYPE my_type (t1 text,t2 int,t3 date);

或者如果现有表的类型匹配,则可以使用表名称作为复合类型.

或者如果您只需要临时类型,您可以创建一个TEMPORARY TABLE,它在会话期间注册一个临时类型:

  1. CREATE TEMP TABLE my_type (t1 text,t3 date);

你甚至可以为一个单一的交易:

  1. CREATE TEMP TABLE my_type (t1 text,t3 date) ON COMMIT DROP;

那么你可以使用这个查询

  1. SELECT (x.combo).* -- parenthesis required
  2. FROM (
  3. SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
  4. THEN ('test',3,now()::date)::my_type -- example values
  5. ELSE (r2.team_name,r2.int_col,r2.date_col)::my_type
  6. END AS combo
  7. FROM rtp
  8. JOIN rtd2 r2 ON <unknown condition>
  9. ) x;

或者甚至(同上,更简单,更短,也许不太容易理解):

  1. SELECT (CASE WHEN rtp.team_id = rtp.sub_team_id
  2. THEN ('test',now()::date)::my_type
  3. ELSE (r2.team_name,r2.date_col)::my_type
  4. END).*
  5. FROM rtp
  6. JOIN rtd2 r2 ON <unknown condition>;

CASE表达式通过这种方式对每一列进行一次评估.如果评估不是微不足道,另一个具有子查询的变体会更快.

猜你在找的Postgre SQL相关文章