我有一个总是返回单个数组的 SQL 子查询。我希望我的外部查询过滤值在该数组中的位置。我期望的工作都没有为此工作。
最小测试设置:
CREATE TABLE test (num int);
INSERT INTO test (num) values (1);
INSERT INTO test (num) values (2);
我尝试的查询应该返回两行,“1”和“2”:
SELECT * FROM test WHERE num = ANY(SELECT array_agg(num) from test);
当然... 错误:运算符不存在:integer = integer[]
。子查询返回包含一个数组的一行,我只需要获取该数组。
也尝试过,但没有成功:
SELECT * FROM test WHERE num = ANY((SELECT array_agg(num) from test)[0]);
我收到错误:op ANY/ALL (array) requires array on right side
。这对我来说没有意义,但我不是专家。
我应该在这里做什么?
最佳答案
第一个错误是因为 PostgreSQL 看到了
num = ANY(SELECT array_agg(num) from test)
作为一种形式
expression operator ANY (subquery)
而不是你想要的:
expression operator ANY (array expression)
因此,它尝试将 num
与子查询返回的任何 ROW 进行比较(在您的示例中返回单行 ARRAY[1,2]
),而不是数组的每个元素(因此 operator does not exist: integer = integer[]
你得到的错误)。参见 the documentation了解更多详情。
第二个错误仅仅是因为 [0]
访问了 integer[]
的一个元素,因此返回了一个 integer
。由于正确的操作数必须是数组(或子查询,但 PostgreSQL 在这里看不到),PostgreSQL 返回 ERROR: op ANY/ALL (array) requires array on right side
。
(顺便说一句,数组在 PostgreSQL 中是从 1 开始的,而不是从 0 开始的)。
如果您确定您的函数将始终返回一个单个 数组,那么您可以简单地强制 Postgre 看到 SELECT array_agg(num) from test
作为 integer[]
:
SELECT * FROM test
WHERE num = ANY((SELECT array_agg(num) from test)::integer[]);
┌─────┐
│ num │
├─────┤
│ 1 │
│ 2 │
└─────┘
(2 rows)
但是请注意,如果您的函数返回多个数组,您将收到错误消息(因为 setof integer[]
不能被视为 integer[]
):
SELECT * FROM test
WHERE num = ANY((SELECT array_agg(num) from test GROUP BY num)::integer[]);
ERROR: 21000: more than one row returned by a subquery used as an expression
LOCATION: ExecSetParamPlan, nodeSubplan.c:970
另一种解决方案是使用 unnest
函数将数组转换为一组整数,使用 表达式运算符 ANY(子查询)
形式。即使您的函数返回多个数组,这也会起作用,尽管它比之前的查询慢一点。
SELECT *
FROM test
WHERE num = ANY(
SELECT unnest(sub.array_agg)
FROM (
SELECT array_agg(num) FROM test GROUP BY num -- GROUP BY num to show off the multiple array scenario
) AS sub
);
┌─────┐
│ num │
├─────┤
│ 1 │
│ 2 │
└─────┘
(2 rows)
关于sql - 从 SQL 子查询中展开行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32407550/