在Postgres9.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要求我将integer[]转换为integer[]?没有道理。
最佳答案
内部选择(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
则无法工作,因为FROM子句需要resultset,而不是整数数组。
但是,可以将包含一行一列的resultset强制转换为该singleton类型的实例(在本例中为integer[]
)。这消除了“我正在查找此子查询的任何行”与“我正在查找此子查询的单个行/列的数组”之间的歧义。
因此,需要显式转换。
关于arrays - 是否需要不必要的postgres数组转换?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27274400/