PostgreSQL 中的 IN 与 ANY 运算符

Posted

技术标签:

【中文标题】PostgreSQL 中的 IN 与 ANY 运算符【英文标题】:IN vs ANY operator in PostgreSQL 【发布时间】:2016-04-10 04:24:00 【问题描述】:

PostgreSQL 中INANY 运算符有什么区别? 两者的工作机制似乎是一样的。谁能举个例子解释一下?

【问题讨论】:

postgreSQL - in vs any的可能重复 这能回答你的问题吗? Difference between in and any operators in sql 【参考方案1】:

INANY 都不是“运算符”。“构造”或“语法元素”。)

逻辑上,quoting the manual:

IN 等价于= ANY

但是IN 有两个语法变体ANY 有两个变体。详情:

How to use ANY instead of IN in a WHERE clause with Rails?

IN 接受一个集合相当于= ANY接受一个集合,如下所示:

postgreSQL - in vs any

但每个变体的第二个变体并不等同于另一个。 ANY 构造的第二个变体采用 array(必须是实际的数组类型),而 IN 的第二个变体采用逗号分隔的 值列表。这导致传值的限制不同,可以在特殊情况下也会导致不同的查询计划:

Index not used with =any() but used with in Pass multiple sets or arrays of values to a function How to match elements in an array of composite type?

ANY 更通用

ANY 结构更加通用,因为它可以与各种运算符组合,而不仅仅是=。示例:

SELECT 'foo' LIKE ANY('FOO,bar,%oo%');

对于大量值,提供 set 可以更好地扩展每个值:

Optimizing a Postgres query with a large IN

相关:

Can PostgreSQL index array columns?

反转/相反/排除

“查找id 在给定数组中的行”:

SELECT * FROM tbl WHERE id = ANY (ARRAY[1, 2]);

反转:“查找数组中id 的行”:

SELECT * FROM tbl WHERE id <> ALL (ARRAY[1, 2]);
SELECT * FROM tbl WHERE id <> ALL ('1, 2');  -- equivalent array literal
SELECT * FROM tbl WHERE NOT (id = ANY ('1, 2'));

所有三个等效项。第一个是array constructor,另外两个是array literal。数据类型可以明确地从上下文中派生。否则,可能需要显式转换,例如 '1,2'::int[]

带有 id IS NULL 的行不会通过这些表达式中的任何一个。额外包含NULL 值:

SELECT * FROM tbl WHERE (id = ANY ('1, 2')) IS NOT TRUE;

【讨论】:

最好明确说明第二个变体的结果总是相同的。我有 99% 的把握确实是这样,但答案似乎并没有说明这一点。这意味着SELECT * from mytable where id in (1, 2, 3) 将始终产生与SELECT * from mytable where id = ANY('1, 2, 3') 相同的行,即使它们可能具有不同的查询计划。 ANY 不能!= 运算符结合使用。我认为它没有记录在案,但select * from foo where id != ANY (ARRAY[1, 2])select * from foo where id NOT IN (1, 2) 不同。另一方面,select * from foo where NOT (id = ANY (ARRAY[1, 2])) 按预期工作。 @qris: ANY 可以与!= 运算符结合使用。但还有更多。我在上面添加了一章。 (请注意,&lt;&gt; 是标准 SQL 中的运算符 - 尽管 Postgres 也接受 !=。) 最后一个包含NULL 值的版本是如何工作的? WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL; 也能正常工作吗? @dvtan: (id = ...) IS NOT TRUE 有效,因为id = ... 仅在存在实际匹配时才计算为TRUE。结果FALSENULL 通过了我们的测试。见:***.com/a/23767625/939860。您添加的表达式测试其他内容。这相当于WHERE id &lt;&gt; ALL (ARRAY[1, 2]) OR id IS NULL;【参考方案2】:

有两个明显的点,以及另一个答案中的点:

在使用子查询时,它们是完全等价的:

SELECT * FROM table
WHERE column IN(subquery);

SELECT * FROM table
WHERE column = ANY(subquery);

另一方面:

只有IN 运算符允许简单列表:

SELECT * FROM table
WHERE column IN(… , … , …);

当我忘记ANY 不适用于列表时,假设它们完全相同,这让我好几次感到困惑。

【讨论】:

以上是关于PostgreSQL 中的 IN 与 ANY 运算符的主要内容,如果未能解决你的问题,请参考以下文章

postgreSQL - 在与任何

postgresql----ANY/SOME&&ALL

PostgreSQL 12.2 公开课及视频及PGCE认证(第10期)(CUUG)(2020年)

MySQL 运算符

PostgreSQL 子查询

PostgreSQL 子查询