postgresql Postgres不在数组中

ruoxqz4g  于 2022-11-04  发布在  PostgreSQL
关注(0)|答案(8)|浏览(307)

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

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

ycggw6v2

ycggw6v21#

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

您始终可以使用WHERE NOT (condition)求反WHERE (condition)

bmp9r5qi

bmp9r5qi2#

您可以将它稍微转一转,然后说“3不等于所有ID”:

where 3 != all (recipient_ids)

从精细手册:

9.21.4.全部(数组)

expression operator ALL (array expression)

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

h4cxqtbf

h4cxqtbf3#

注意空值

两者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的结果将为空

e0bqpujr

e0bqpujr4#

扩充ALL/ANY答案

我更喜欢使用allany来实现结果的所有解决方案,欣赏额外的注解(例如,关于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想要的。

uyto3xhc

uyto3xhc5#

更新:
从postgres 9.3开始,
您也可以将NOT@>(contains operator)结合使用来实现这一点。
即:
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];

6jygbczu

6jygbczu6#

一个月一个月?

vbkedwbf

vbkedwbf7#

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

5sxhfpxr8#

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

相关问题