我使用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))
检测这种情况的正确方法是什么?
8条答案
按热度按时间ycggw6v21#
您始终可以使用
WHERE NOT (condition)
求反WHERE (condition)
bmp9r5qi2#
您可以将它稍微转一转,然后说“3不等于所有ID”:
从精细手册:
9.21.4.全部(数组)
右边是一个带括号的表达式,它必须生成一个数组值。左边的表达式使用给定的***运算符***进行计算并与数组中的每个元素进行比较。它必须产生布尔结果。如果所有比较结果都为true,则
ALL
的结果为“true(包括数组中没有元素的情况)。如果发现任何false结果,则结果为“false”。h4cxqtbf3#
注意空值
两者
ALL
:和
ANY
:只要
some_array
不为空,就可以使用。如果数组可能为空,则必须使用coalesce()将其考虑在内,例如:或者
从文档中:
如果数组表达式生成空数组,则ANY的结果将为空
如果数组表达式生成空数组,则ALL的结果将为空
e0bqpujr4#
扩充
ALL/ANY
答案我更喜欢使用
all
或any
来实现结果的所有解决方案,欣赏额外的注解(例如,关于NULLs)。作为另一个补充,这里有一种考虑这些操作符的方法。你可以把它们想象成 * 短路运算符 *:
all(array)
遍历数组中的所有值,并使用提供的运算符将每个值与参考值进行比较。一旦比较结果为false
,则该过程以false结束,否则以true结束。(相当于短路逻辑and
。)any(array)
遍历数组中的所有值,并使用提供的运算符将每个值与参考值进行比较。一旦比较结果为true
,则该过程以true结束,否则以false结束。(类似于短路逻辑or
。)这就是
3 <> any('{1,2,3}')
无法产生所需结果的原因:该过程将3与1进行比较,如果不相等,则立即返回true。数组中的单个值与3不同,就足以使整个条件为true。最后一个数组位置中的3可能从未使用过。另一方面,
3 <> all('{1,2,3}')
确保 all 值不等于3。它将遍历所有产生true的比较,直到一个产生false的元素(在本例中是最后一个),以返回false作为总结果。这就是OP想要的。uyto3xhc5#
更新:
从postgres 9.3开始,
您也可以将
NOT
与@>
(contains operator)结合使用来实现这一点。即:
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];
6jygbczu6#
一个月一个月?
vbkedwbf7#
请注意,ANY/ALL运算符不适用于数组索引。如果需要索引:
而消极的一面是:
然后可以创建索引,如下所示:
5sxhfpxr8#
使用以下查询从示例中选择id,其中NOT(id = ANY('{1,2}'))