Postgres NOT in array

我正在使用 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))

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

123669 次浏览
SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))

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

not (3 = any(recipient_ids))

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

where 3 != all (recipient_ids)

来自 手册不错:

9.21.4. ALL (array)

expression operator ALL (array expression)

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

请注意,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)

最新消息:

截至邮政9.3,

您可以使用 NOT@> (包含操作员)协同实现这一点。

IE.

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

小心 NULL

ALL:

(some_value != ALL(some_array))

还有 ANY:

NOT (some_value = ANY(some_array))

只要 some_array不为空就可以工作。如果数组可能为 null,那么您必须使用联合()对其进行说明,例如。

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

或者

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

来自 医生:

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

如果数组表达式生成空数组,则 ALL 的结果为空

增强 ALL/ANY答案

我更喜欢所有使用 allany的解决方案,欣赏附加的音符(例如关于 无效)。作为另一个增强,这里有一种思考这些运算符的方法。

你可以把它们想象成 短路操作员短路操作员:

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

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

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

使用以下查询 选择示例中的 id,其中 NOT (id = ANY (’{1,2}’))