125

我正在使用 Postgres 的本机数组类型,并尝试查找 ID 不在数组收件人 ID 中的记录。

我可以找到他们在哪里:

SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))

但这不起作用:

SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3  = NOT ANY (recipient_ids))

测试这种情况的正确方法是什么?

4

7 回答 7

164
SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))

你总是可以WHERE (condition)否定WHERE NOT (condition)

于 2012-07-30T22:44:14.540 回答
47

你可以把它转过来说“3 不等于所有的 ID”:

where 3 != all (recipient_ids)

来自精美手册

9.21.4。全部(数组)

expression operator ALL (array expression)

右边是一个带括号的表达式,它必须产生一个数组值。使用给定的operator计算左侧表达式并与数组的每个元素进行比较,这必须产生一个布尔结果。ALL如果所有比较结果为真(包括数组元素为零的情况),则结果为“真”。如果发现任何错误结果,则结果为“错误”。

于 2012-07-30T22:51:32.803 回答
29

增加ALL/ANY答案

我更喜欢所有使用allany实现结果的解决方案,欣赏附加说明(例如关于NULL s)。作为另一种扩展,这里有一种考虑这些运算符的方法。

您可以将它们视为短路运算符

  • all(array)遍历数组中的所有值,使用提供的运算符将每个值与参考值进行比较。一旦比较产生false,该过程以假结束,否则为真。(类似于短路逻辑and。)
  • any(array)遍历数组中的所有值,使用提供的运算符将每个值与参考值进行比较。一旦比较产生true,该过程以真结束,否则以假结束。(类似于短路逻辑or。)

这就是为什么3 <> any('{1,2,3}')不产生预期结果的原因:该过程将 3 与 1 进行比较以判断不等式,结果为真,并立即返回真。数组中不同于 3 的单个值足以使整个条件为真。最后一个数组位置的 3 是概率。没用过。

3 <> all('{1,2,3}')另一方面,确保所有值不等于 3。它将运行所有产生 true 的比较,直到产生 false 的元素(在本例中为最后一个),以返回 false 作为整体结果。这就是OP想要的。

于 2018-05-03T15:14:05.567 回答
25

谨防空值

两者ALL

(some_value != ALL(some_array))

并且ANY

NOT (some_value = ANY(some_array))

只要some_array不为空就可以工作。如果数组可能为空,那么您必须使用 coalesce() 来处理它,例如

(some_value != ALL(coalesce(some_array, array[]::int[])))

或者

NOT (some_value = ANY(coalesce(some_array, array[]::int[])))

文档

如果数组表达式产生一个空数组,则 ANY 的结果将为空

如果数组表达式产生一个空数组,则 ALL 的结果将为空

于 2018-03-01T02:21:50.887 回答
14

更新:

从 postgres 9.3 开始,

您也可以NOT@> (contains operator)一起使用来实现这一点。

IE。

SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];

于 2017-04-12T22:13:38.250 回答
13

not (3 = any(recipient_ids))?

于 2012-07-30T22:44:50.827 回答
3

请注意,ANY/ALL 运算符不适用于数组索引。如果考虑索引:

SELECT COUNT(*) FROM "messages" WHERE 3 && recipient_ids

和否定:

SELECT COUNT(*) FROM "messages" WHERE NOT (3 && recipient_ids)

然后可以像这样创建索引:

CREATE INDEX recipient_ids_idx on tableName USING GIN(recipient_ids)
于 2014-06-20T14:56:23.037 回答