PostgreSQL中的IN与ANY运算符


Answers:


157

(“操作符” IN也不ANY是。“构造”或“语法元素”。)

从逻辑上讲引用该手册

IN等同于= ANY

但有两个语法变种IN和两个变种ANY。细节:

IN 采取一个集合等同于= ANY采取一个set,如此处所示:

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

ANY 更通用

ANY结构的用途更加广泛,因为它可以与各种运算符(而不仅仅是)结合使用=。例:

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

对于大量值,为每个值提供更好的设定范围:

有关:

反转/相反/排除

“查找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}'));

所有三个相等。第一个带有数组构造函数,其他两个带有数组文字。数据类型可以明确地从上下文派生。否则,可能需要显式强制转换,例如'{1,2}'::int[]

具有的id IS NULL行不会传递这些表达式中的任何一个。要NULL另外包含值:

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

4
最好明确阐明第二个变体的结果将始终相同。我有99%的肯定是这样,但答案似乎并没有说明。这意味着,即使它们可能具有不同的查询计划,它们也SELECT * from mytable where id in (1, 2, 3)将始终与产生相同的行SELECT * from mytable where id = ANY('{1, 2, 3}')
KPD

1
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

1
@qris:ANY可以与!=运算符结合使用。但是还有更多。我在上面添加了一章。(请注意,这<>是标准SQL中的运算符-尽管!=在Postgres中也被接受。)
Erwin Brandstetter,

最后一个包含NULL值的版本如何工作?会WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;一样好吗?
dvtan

1
@dvtan:(id = ...) IS NOT TRUE之所以起作用,是因为id = ...仅计算TRUE是否存在实际匹配。结果FALSENULL通过我们的测试。请参阅:stackoverflow.com/a/23767625/939860。您添加的表达式将测试其他内容。这将是等效的WHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Erwin Brandstetter

3

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

  • 当使用子查询时,它们是完全等效的:

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

另一方面:

  • IN操作员允许一个简单的列表:

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

假设它们是完全一样的,而忘记ANY了列表不起作用时,我已经被吸引了好几次。

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.