Postgres不在数组中

use*_*808 78 arrays postgresql

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

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

SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))
Run Code Online (Sandbox Code Playgroud)

但这不起作用:

SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3  = NOT ANY (recipient_ids))
Run Code Online (Sandbox Code Playgroud)

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

Fra*_*mer 110

SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))
Run Code Online (Sandbox Code Playgroud)

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

  • @aschyiel——随着“recipient_ids”输入列表的增长,您可能希望切换回“ANY”而不是“IN”:http://stackoverflow.com/questions/1009706/postgresql-max-number-of-parameters-在条款 (2认同)

mu *_*ort 36

你可以把它转过来说"3不等于所有ID":

where 3 != all (recipient_ids)
Run Code Online (Sandbox Code Playgroud)

精细手册:

9.21.4.ALL(数组)

expression operator ALL (array expression)
Run Code Online (Sandbox Code Playgroud)

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

  • 添加此内容是因为 @seanlinsley 的评论。即使只有一个评估为“true”,“any([array])”也会返回“true”。因此,如果您有“where 3 != any([1,3])”(所需输出为“false”),您将得到“true”,因为该表达式的计算结果为“3!=1 == true”和“3! =3 == 假`。现在你有“any(true,false)”;这将返回“true”(这不是您想要的)。相比之下, `3 != all([1,3])` 的计算结果为 `3!=1 == true` 和 `3!=3 == false` 现在您有 `all(true,false)` 计算结果到“false”(这就是您一直想要的)。 (4认同)

Tho*_*asH 13

扩大ALL/ANY答案

我更喜欢使用allany达到结果的所有解决方案,感谢其他注释(例如,关于NULL的注释)。作为另一个补充,这是一种考虑这些运算符的方法。

您可以将它们视为短路算子

  • all(array)遍历数组中的所有值,并使用提供的运算符将每个值与参考值进行比较。比较产生后false,该过程以false结束,否则为true。(相当于短路逻辑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想要的。


Mar*_*nen 10

not (3 = any(recipient_ids))


Roo*_*ter 9

更新:

截至postgres 9.3,

您可以NOT@> (包含运算符)一起使用来实现此目的.

IE浏览器.

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


isa*_*pir 7

当心NULL

两者ALL

(some_value != ALL(some_array))
Run Code Online (Sandbox Code Playgroud)

ANY

NOT (some_value = ANY(some_array))
Run Code Online (Sandbox Code Playgroud)

只要some_array不为null,就可以使用。如果数组可能为空,则必须使用Coalesce()进行解释,例如

(some_value != ALL(coalesce(some_array, array[]::int[])))
Run Code Online (Sandbox Code Playgroud)

要么

NOT (some_value = ANY(coalesce(some_array, array[]::int[])))
Run Code Online (Sandbox Code Playgroud)

文档

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

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