IN vs ANY operator in PostgreSQL

后端 未结 2 583
挽巷
挽巷 2020-11-27 11:14

What is the difference between IN and ANY operator in PostgreSQL?
The working mechanism of both seems to be the same. Can anyone explain this w

相关标签:
2条回答
  • 2020-11-27 11:28

    There are two obvious points, as well as the points in the other answer:

    • They are exactly equivalent when using sub queries:

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

    On the other hand:

    • Only the IN operator allows a simple list:

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

    Presuming they are exactly the same has caught me out several times when forgetting that ANY doesn’t work with lists.

    0 讨论(0)
  • 2020-11-27 11:48

    (Neither IN nor ANY is an "operator". A "construct" or "syntax element".)

    Logically, quoting the manual:

    IN is equivalent to = ANY.

    But there are two syntax variants of IN and two variants of ANY. Details:

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

    IN taking a set is equivalent to = ANY taking a set, as demonstrated here:

    • postgreSQL - in vs any

    But the second variant of each is not equivalent to the other. The second variant of the ANY construct takes an array (must be an actual array type), while the second variant of IN takes a comma-separated list of values. This leads to different restrictions in passing values and can also lead to different query plans in special cases:

    • Index not used with =any() but used with in
    • Pass multiple sets or arrays of values to a function

    ANY is more versatile

    The ANY construct is far more versatile, as it can be combined with various operators, not just =. Example:

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

    For a big number of values, providing a set scales better for each:

    • Optimizing a Postgres query with a large IN

    Related:

    • Can PostgreSQL index array columns?

    Inversion / opposite / exclusion

    "Find rows where id is in the given array":

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

    Inversion: "Find rows where id is not in the array":

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

    All three equivalent. The first with array constructor, the other two with array literal. The data type can be derived from context unambiguously. Else, an explicit cast may be required, like '{1,2}'::int[].

    Rows with id IS NULL do not pass either of these expressions. To include NULL values additionally:

    SELECT * FROM tbl WHERE (id = ANY ('{1, 2}')) IS NOT TRUE;
    
    0 讨论(0)
提交回复
热议问题