如何在 WHERE 子句中使用 ANY 而不是 IN?

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

我曾经有一个像 Rails 中的查询:

MyModel.where(id: ids)

生成 sql 查询,如:

SELECT "my_models".* FROM "my_models"
WHERE  "my_models"."id" IN (1, 28, 7, 8, 12)

现在我想将其更改为使用 ANY 而不是 IN。我创建了这个:

MyModel.where("id = ANY(VALUES(#{ids.join '),('}))"

现在,当我使用空数组 ids = [] 时,出现以下错误:

MyModel Load (53.0ms)  SELECT "my_models".* FROM "my_models"  WHERE (id = ANY(VALUES()))
ActiveRecord::JDBCError: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"
ActiveRecord::StatementInvalid: ActiveRecord::JDBCError: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"
Position: 75: SELECT "social_messages".* FROM "social_messages"  WHERE (id = ANY(VALUES()))
    from arjdbc/jdbc/RubyJdbcConnection.java:838:in `execute_query'

IN 表达式有两种变体:

类似地,具有 ANY 构造的两个变体:

子查询适用于任何一种技术,但对于每种技术的 second 形式,IN 需要一个 值列表 (如标准 SQL 中所定义)而 = ANY 需要一个 数组 .

使用哪个?

ANY 是后来更通用的加法,它可以与任何返回布尔值的二元运算符结合使用。 IN 归结为 ANY 的特例。其实它的第二种形式是内部改写的:

IN 改写为 = ANY
NOT IN 改写为 <> ALL

检查 EXPLAIN 输出以了解任何查询。这证明了两件事:

  • IN 永远不会比 = ANY.
  • = ANY 不会明显变快。

应根据哪个更容易提供来决定:值列表或数组(可能是数组文字 - 单个值)。

如果您要传递的 ID 来自数据库 无论如何,直接 select 它们(子查询)或集成源会更有效table 进入带有 JOIN 的查询(例如 )。

从您的客户端传递一个 长列表 值并获得最佳 性能,使用数组,unnest() 并连接,或使用 VALUES(如 )将其作为 table 表达式提供。但请注意,JOIN 会在提供的数组/集合中保留可能的 重复项 ,而 IN= ANY 则不会。更多:

在存在 NULL 值的情况下,NOT IN 通常是错误的选择,而 NOT EXISTS 是正确的(而且速度也更快):

  • Select rows which are not present in other table

= ANY

的语法

对于 Postgres 接受的数组表达式:

为避免无效类型转换,您可以显式转换:

ARRAY[1,2,3]::numeric[]
'{1,2,3}'::bigint[]

相关:

  • How to pass custom type array to Postgres function

或者您 可以 创建一个带有 VARIADIC 参数的 Postgres 函数,它接受单独的参数并从中形成一个数组:

如何从Ruby传递数组?

假设 idinteger:

MyModel.where('id = ANY(ARRAY[?]::int[])', ids.map { |i| i})

但我只是涉足Ruby。 @mu 在此相关答案中提供了详细说明:

  • Sending array of values to a sql query in ruby?