在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要求我将整数[]转换为整数[]?没有意义。
答案 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}})。这消除了“我正在查看此子查询的任何行”之间的歧义“我正在查看此子查询的单行/列的数组”。
因此,要求明确施放。