Postgres不在数组中


96

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

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


WHERE 3 NOT IN recipient_ids工作?
Janus Troelsen,2012年

1
相关注意事项:text[]int[]排列一样:select not(array[1,2,3] @> array[3]);
史蒂夫·皮克

3
专家提示:如果要检查null数组中是否包含某列,则该列将始终拒绝。我花了20分钟就好调试几种含方法来得出的结论是,如果null被包含在数组中,你不能签
安德烈·佩纳

Answers:



39

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

where 3 != all (recipient_ids)

精美的手册中

9.21.4。全部(数组)

expression operator ALL (array expression)

右边是带括号的表达式,必须产生一个数组值。将使用给定的运算符评估左侧表达式并将其与数组的每个元素进行比较,该运算符必须产生布尔结果。ALL如果所有比较都得出true(包括数组中元素为零的情况),则结果为“ true”。如果找到任何错误结果,则结果为“ false”。


这并不能真正解释为什么any在这种情况下
不起作用

这应该被接受,因为它可以正确解释原因。PS你也可以找到anyall在Postgres的文档,它说:“ x <> ANY (a,b,c) 相当于x <> a OR <> b OR x <> c”。参考: postgresqltutorial.com/postgresql-any postgresqltutorial.com/postgresql-all
Tyler Temp

19

扩大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想要的。




11

当心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[])))

文档

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

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


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)

与其他答案不同,该答案实际上利用了PostgreSQL数组重叠运算符。&&
壁虎

6
这将无法正常工作。像&&和@>这样的数组运算符要求两个元素都必须是数组,而3则不是。为了使它起作用,查询将需要编写为:SELECT COUNT(*) FROM "messages" WHERE ARRAY[3] && recipient_ids
Dologan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.