我曾经有一个类似于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'
1条答案
按热度按时间0g0grzrc1#
IN
表达式有两种变体:expression IN (subquery)
expression IN (value [, ...])
类似地,具有
ANY
结构的两个变体:expression operator ANY (subquery)
expression operator ANY (array expression)
子查询适用于这两种技术,但是对于每种技术的第二种形式,
IN
需要一个值列表(如标准SQL中定义的),而= ANY
需要一个数组。使用哪一个?
ANY
是一个后来的、更通用的加法运算,它可以与任何返回布尔值的二元运算符组合使用。IN
被简化为ANY
的一个特例。事实上,它的第二种形式是在内部重写的:使用
= ANY
重写IN
使用
<> ALL
重写NOT IN
检查
EXPLAIN
输出中的任何查询,以亲自查看。IN
永远不会比= ANY
快。= ANY
不会有实质性的提高。选择应取决于哪个更容易提供:值列表或数组(可能作为数组文字-单个值)。
如果您要传递的ID来自DB内部,直接选择它们(子查询)或使用
JOIN
(如@mu注解)将源表集成到查询中会更有效。要从客户端传递一个***长列表*并获得最佳*性能***,请使用数组
unnest()
和join,或使用VALUES
将其作为表表达式提供(就像@PinnyM评论的那样)。但是注意,JOIN
在提供的数组/集合中保留了可能的重复项,而IN
或= ANY
则没有。更多信息:如果存在NULL值,
NOT IN
通常是错误的选择,而NOT EXISTS
是正确的(而且速度更快):= ANY
的语法对于Postgres接受的数组表达式:
ARRAY[1,2,3]
'{1,2,3}'
形式的数组文字量。若要避免无效的类型转换,可以显式转换:
相关:
或者,你可以创建一个带
VARIADIC
参数的Postgres函数,该函数接受单个参数并将它们组成一个数组:如何从Ruby传递数组?
假设
id
等于integer
:但我只是在涉猎Ruby。@mu在这个相关的答案中提供了详细的说明: