我正在使用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))
测试这种情况的正确方法是什么?
答案 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
答案我更喜欢使用all
或any
的所有解决方案来实现结果,并欣赏其他注释(例如关于 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)
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)