【问题标题】: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 关系,现在你可以玩得开心了!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-08-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-14
          • 1970-01-01
          • 2014-09-26
          相关资源
          最近更新 更多