【发布时间】:2016-04-10 04:24:00
【问题描述】:
PostgreSQL 中IN 和ANY 运算符有什么区别?
两者的工作机制似乎是一样的。谁能举个例子解释一下?
【问题讨论】:
标签: sql database postgresql rdbms sql-in
PostgreSQL 中IN 和ANY 运算符有什么区别?
两者的工作机制似乎是一样的。谁能举个例子解释一下?
【问题讨论】:
标签: sql database postgresql rdbms sql-in
(IN 和 ANY 都不是“运算符”。“构造”或“语法元素”。)
逻辑上,quoting the manual:
IN等价于= ANY。
但是IN 有两个语法变体,ANY 有两个变体。详情:
IN 接受一个集合相当于= ANY接受一个集合,如下所示:
但每个变体的第二个变体并不等同于另一个。 ANY 构造的第二个变体采用 array(必须是实际的数组类型),而 IN 的第二个变体采用逗号分隔的 值列表。这导致传值的限制不同,可以在特殊情况下也会导致不同的查询计划:
=any() but used with inANY 更通用ANY 结构更加通用,因为它可以与各种运算符组合,而不仅仅是=。示例:
SELECT 'foo' LIKE ANY('{FOO,bar,%oo%}');
对于大量值,提供 set 可以更好地扩展每个值:
相关:
“查找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;
【讨论】:
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])) 按预期工作。
ANY 可以与!= 运算符结合使用。但还有更多。我在上面添加了一章。 (请注意,<> 是标准 SQL 中的运算符 - 尽管 Postgres 也接受 !=。)
NULL 值的版本是如何工作的? WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL; 也能正常工作吗?
(id = ...) IS NOT TRUE 有效,因为id = ... 仅在存在实际匹配时才计算为TRUE。结果FALSE 或NULL 通过了我们的测试。见:stackoverflow.com/a/23767625/939860。您添加的表达式测试其他内容。这相当于WHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
有两个明显的点,以及另一个答案中的点:
在使用子查询时,它们是完全等价的:
SELECT * FROM table
WHERE column IN(subquery);
SELECT * FROM table
WHERE column = ANY(subquery);
另一方面:
只有IN 运算符允许简单列表:
SELECT * FROM table
WHERE column IN(… , … , …);
当我忘记ANY 不适用于列表时,假设它们完全相同,这让我好几次感到困惑。
【讨论】: