Postgres不在数组中

时间:2012-07-30 22:42:11

标签: arrays postgresql

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

我可以找到他们在哪里IN:

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))

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

7 个答案:

答案 0 :(得分:101)

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

您始终可以使用WHERE (condition)

否定WHERE NOT (condition)

答案 1 :(得分:32)

你可以稍微转过来说“3不等于所有ID”:

where 3 != all (recipient_ids)

来自fine manual

  

<强> 9.21.4。 ALL(数组)

expression operator ALL (array expression)
     

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

答案 2 :(得分:9)

not (3 = any(recipient_ids))

答案 3 :(得分:8)

扩充ALL/ANY答案

我更喜欢使用allany的所有解决方案来实现结果,并欣赏其他注释(例如关于 NULL s)。作为另一种审查,这是一种思考这些运营商的方法。

您可以将它们视为短路运营商

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

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

另一方面,

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

答案 4 :(得分:7)

更新:

截至postgres 9.3,

您可以NOT@> (contains operator)同时使用,以实现这一目标。

IE。

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

答案 5 :(得分:4)

小心NULL

ALL

(some_value != ALL(some_array))

ANY

NOT (some_value = ANY(some_array))

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

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

或者

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

来自docs

  

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

     

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

答案 6 :(得分: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)