【问题标题】:Nested Case statement type error (postgres)嵌套 Case 语句类型错误(postgres)
【发布时间】:2015-12-03 22:56:46
【问题描述】:

我创建的一些 postgres 代码给了我一个错误:

ERROR:  CASE types character varying and numeric cannot be matched

代码:

CREATE TABLE current_condition_joined AS SELECT
a.id, a.geom, a.condition_join_1, a.condition_join_2, a.condition_join_3,
(CASE WHEN b.condition = 'ERROR' THEN (CASE WHEN c.condition2 = 'ERROR' THEN d.condition3
                                       ELSE c.condition2
                                       END)
 ELSE b.condition
 END) current_condition,
(CASE WHEN b.condition= 'ERROR' THEN (CASE WHEN c.condition2 = 'ERROR' THEN d.ecosite3
                                      ELSE c.ecosite2
                                      END)
 ELSE b.ecosite
 END) current_ecosite,
(CASE WHEN b.condition = 'ERROR' THEN (CASE WHEN c.condition2 = 'ERROR' THEN d.ecophase3
                                       ELSE c.ecophase2
                                       END)
 ELSE b.ecophase
 END) current_ecophase,
(CASE WHEN b.condition = 'ERROR' THEN (CASE WHEN c.condition2 = 'ERROR' THEN d.consite3
                                       ELSE c.consite2
                                       END)
 ELSE b.consite
 END) current_consite,
(CASE WHEN b.condition = 'ERROR' THEN (CASE WHEN c.condition2 = 'ERROR' THEN d.conphase3
                                       ELSE c.conphase2
                                       END)
 ELSE b.conphase
 END) current_conphase
 FROM current_condition a, boreal_mixedwood_labeled b, boreal_mixedwood_labeled c, boreal_mixedwood_labeled d
 WHERE a.label = b.label_join_1
   and a.label2 = c.label_join_2
   and a.label3 = d.label_join_3;

b、c、d ecosite 和 phase 都是数字类型。唯一的条件是 varchar。

在第二列和第三列中,出现问题的地方是创作。我假设我得到了错误,因为它在引用 varchar 的情况下的第一部分,但第二种情况的结果是数字。我想使用条件“错误”来选择要使用的数值。

我是 postgres (9.4.5) 的新手,但对 sql 相当精通。我在 Windows 机器上的 pgAdmin (v. 1.18.1) 中工作。

我查看了我的问题的其他实例,但他们不考虑嵌套语句。 What's wrong with my CASE?

在 PGAdmin 的 SQL 窗格中创建表 current_condition 的代码:

CREATE TABLE current_condition (
  geom geometry,
  condition_join_1 text,
  condition_join_2 text,
  condition_join_3 text,
  id serial NOT NULL,
  CONSTRAINT current_condition_pkey PRIMARY KEY (id)
);

CREATE INDEX idx_current_condition_geom
  ON current_condition USING gist (geom);

boreal_mixedwood_labeled 表的代码:

CREATE TABLE boreal_mixedwood_labeled
(
  objectid serial NOT NULL,
  label character varying(255),
  label2 character varying(255),
  label3 character varying(255),
  condition character varying(255),
  ecophase numeric(15,6),
  ecosite numeric(15,6),
  conphase character varying(255),
  consite character varying(255),
  condition2 character varying(255),
  ecophase2 numeric(15,6),
  ecosite2 numeric(15,6),
  conphase2 character varying(255),
  consite2 character varying(255),
  condition3 character varying(255),
  ecophase3 numeric(15,6),
  ecosite3 numeric(15,6),
  conphase3 character varying(255),
  consite3 character varying(255),
  CONSTRAINT boreal_mixedwood_labeled_pkey PRIMARY KEY (objectid)

ERWIN 的回答是正确的。虽然列中的值是数字,但表格出于某种原因将它们作为字符。一定是从我的导入中自动发生的。

【问题讨论】:

  • 您忘记了 geom 和您的 Postgres 版本的表限定条件。请将两者都添加到问题中。理想情况下,您将添加表定义以快速澄清事情(您在 psql 中使用 \d tbl 得到什么)。
  • 抱歉,postgres 的新手...geom 的表限定是什么意思??
  • geom 来自哪个表?你有a.id, geom, a.condition_join_1, ... 所以id 和condition_join_1 来自a。还有geom?更一般地说,如果你提供表定义,我可以给你一个更简单的查询,而不是玩这个猜谜游戏。由于您使用的是 pgAdmin:您也可以从 SQL 窗格中复制 CREATE TABLE 脚本。
  • geom 应该来自一个。那是唯一存在的位置几何。 boreal_mixedwood 表是非空间表。为 current_condition 添加了 sql 窗格
  • 快到了。我删除了不相关的部分。你能为boreal_mixedwood_labeled提供同样的服务吗?

标签: sql postgresql pgadmin


【解决方案1】:

尝试消除嵌套的case。也许出于某种原因它会对编译器产生影响:

CASE
    WHEN b.condition = 'ERROR' AND c.condition2 = 'ERROR' THEN d.condition3
    WHEN b.condition = 'ERROR' THEN c.condition2
    ELSE c.condition
END as current_condition,
...

【讨论】:

  • 不过没什么区别。
  • @Erwin,我当然同意它不应该,但它不会是第一次重新排列一个神秘地解决问题的表达式。
  • 试一试不会有什么坏处,但我知道。
【解决方案2】:

正如错误消息告诉您的那样,错误的直接原因是数据类型不匹配。

在第二列和第三列中,创建是问题所在。

CASE 表达式的所有可能结果都需要共享兼容的数据类型,因此它们必须匹配,但显然不匹配。 The manual instructs:

所有 result 表达式的数据类型必须可转换为 单输出类型。详情请见Section 10.5。

假设您引用 current_condition 和 current_ecosite - 实际上是第 6 列和第 7 列,这些需要具有匹配的数据类型:

d.ecosite3
c.ecosite2
b.ecosite

和:

d.ecophase3
c.ecophase2
b.ecophase

更好的查询

等待boreal_mixedwood_labeled 的缺失表定义,我有根据的猜测是您可以从根本上简化此查询:

SELECT a.id, a.geom, a.condition_join_1, a.condition_join_2, a.condition_join_3
     , COALESCE(d.condition3, c.condition2, b.condition) AS current_condition
     , COALESCE(d.ecosite3,   c.ecosite2,   b.ecosite)   AS current_ecosite
     , COALESCE(d.ecophase3,  c.ecophase2,  b.ecophase)  AS current_ecophase
     , COALESCE(d.consite3,   c.consite2,   b.consite)   AS current_consite
     , COALESCE(d.conphase3,  c.conphase2,  b.conphase)  AS current_conphase
FROM   current_condition a
LEFT   JOIN boreal_mixedwood_labeled b ON a.label  = b.label_join_1
LEFT   JOIN boreal_mixedwood_labeled c ON a.label2 = c.label_join_2
                                      AND b.condition = 'ERROR'
LEFT   JOIN boreal_mixedwood_labeled d ON a.label3 = d.label_join_3
                                      AND c.condition2 = 'ERROR';

数据类型仍然必须匹配。

如何?

这不仅更短,而且可能更快。

如果以b.condition = 'ERROR' 开头,则仅第二次加入boreal_mixedwood_labeled,等等。

然后你可以使用更简单的COALESCE 表达式:d.* 是 NULL,除非我们需要它,c.* 也是如此。返回第一个非空值。

如果 boreal_mixedwood_labeled 中的某些列可以为 NULL,则逻辑可能会中断。这一切都取决于...... tada! ...您的实际表定义。 (我提到的足够多了吗?)。不要忘记将它包含在您的下一个问题中......

【讨论】:

  • b、c、d ecosite 和 phase 都是数字类型。唯一的条件是 varchar。从我目前所读的内容来看,似乎第一个案例标识了一个 varchar,所以这就是它在 ecosite 和 ecophase 中寻找的内容。但是,我只需要条件来选择要使用的生态站点和生态阶段的记录。我不知道如何简化它以产生我正在寻找的结果,但这不是我现在所追求的。谢谢
猜你喜欢
  • 1970-01-01
  • 2011-03-12
  • 2016-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-10
  • 1970-01-01
  • 2020-07-29
相关资源
最近更新 更多