需要不必要的postgres阵列拼接?

时间:2014-12-03 14:38:33

标签: arrays postgresql casting any

在Postgres 9.3中进行以下设置:

CREATE TABLE t (id INTEGER);
INSERT INTO t VALUES (1), (2), (3);

我正在将这些值聚合到数组中(不要问为什么,实际设置非常复杂,所以我只需要这种方法)。

现在我需要检查某个整数是否属于该数组。试过这个:

SELECT 1=ANY((SELECT array_agg(id) FROM t))

收到错误:

ERROR:  operator does not exist: integer = integer[]
LINE 1: SELECT 1=ANY((SELECT array_agg(id) FROM t))
                ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

经过一些实验,找到了一个可行的解决方案:

SELECT 1=ANY((SELECT array_agg(id) FROM t)::integer[])

为什么postgres要求我将整数[]转换为整数[]?没有意义。

1 个答案:

答案 0 :(得分:3)

内部选择(SELECT array_agg(id) FROM t)的结果不是integer[],它是一个包含integer[]的单行的结果集。

您可以通过两种方式揭露正在发生的事情。

如果您尝试

SELECT 1=ANY((SELECT array_agg(id) FROM t)::text[]);

错误消息是 ERROR: operator does not exist: integer = text

请注意,错误消息不是指text[],而是指text

这是因为相等性是将左参数与右参数的每个元素进行比较。因此,在原始查询中,它是integer[]的结果集,并且它正在尝试将1与每个integer[]进行比较(您只有一个)select count(*) from (select array_agg(id) from t) as z

另一种看待这种情况的方法是反思

z

这会将您的原始子查询嵌入为z - 并返回1行。如果您尝试将integer[]强制转换为integer[],它将无效 - 因为FROM子句需要结果集,而不是整数数组。

但是,可以将包含一行和一列的结果集转换为该单例类型的实例(在本例中为{{1}})。这消除了“我正在查看此子查询的任何行”之间的歧义“我正在查看此子查询的单行/列的数组”。

因此,要求明确施放。