【问题标题】:How can I do something like find_in_batches_by_sql in Rails如何在 Rails 中执行类似 find_in_batches_by_sql 的操作
【发布时间】:2011-10-11 16:48:31
【问题描述】:
find_in_batches 不允许纯 SQL(据我所知)。
find_by_sql 不支持批处理(据我所知)。
那么我该怎么做find_in_batches_by_sql之类的事情呢?
SQL 是令人讨厌的程序生成的东西,它指向第 3 方数据库,结果集可能返回数十万到数百万条记录。
我应该研究一下 ActiveRecord 的其他光标技巧吗?
谢谢。
【问题讨论】:
标签:
sql
ruby-on-rails
activerecord
【解决方案1】:
更新为使用正确的 LIMIT 和 OFFSET 顺序
您总是可以将 SQL 分成几部分并执行类似的操作
Model.select("*").where("WHERE CLAUSE HERE").joins("JOIN CLAUSES HERE").find_in_batches {...}
或者,如果您需要真正有趣的 SQL 内容,您可以只使用偏移量、限制和循环,直到用尽结果。基本思路如下:
offset = 0
limit = 1000
while(results)
results = Model.find_by_sql("<your SQL here> LIMIT #{limit} OFFSET #{offset}")
offset += limit
# Do stuff here
end
【解决方案2】:
注意偏移量应该在限制之后
offset = 0
limit = 1000
while(results)
results = Model.find_by_sql("<your SQL here> LIMIT #{limit} OFFSET #{offset}")
offset += limit
# Do stuff here
end
【解决方案3】:
与建议的其他答案一样,有一种比重新发明in_batches 功能更方便的方法。
让我们考虑一些我不喜欢翻译成 ActiveRecord 或 Arel 调用的“复杂”SQL(主要是因为我懒得学习 Arel 的语法):
WITH cte AS (
SELECT foo, bar FROM foo_table
)
SELECT id FROM users INNER JOIN cte ON users.foo = cte.foo
您只需选择 id 并将该查询用作 ActiveRecord 关系的子查询,如下所示:
sql_query = "..."
User.where("id IN (#{sql_query})").in_batches.update_all("comment = 'I did it!'")
瞧,你已经有了 ActiveRecord 关系,现在你可以玩得开心了!