【问题标题】:Bound activerecords-queries using aggregate funcs (sum, avg,...) with limit使用具有限制的聚合函数(sum、avg、...)绑定 activerecords 查询
【发布时间】:2013-03-18 11:38:47
【问题描述】:

鉴于这个伪查询:

Model.sum(:column, :condition => ['id = ?', id], order => "date DESC", :limit => X)

这里我们遇到的问题是,获得的总和不受值 X 的“限制”(它将列上的所有值作为总和,而不是 X(第一个)条目的总和)。

看来limit是在计算聚合函数sum之后取的。

我如何才能获得仅受前 X 个条目限制的总和?

【问题讨论】:

    标签: ruby-on-rails-3 model aggregate-functions


    【解决方案1】:

    MurifoX 的建议不起作用,因为LIMIT 仅适用于最终结果集,该结果集只有一行(总和)。见this thread

    解决这个问题的最简单方法是不在数据库中进行计数:

    Model.where(:id => id).order('date DESC').limit(3).pluck(:column).compact.sum
    

    这会将column 的值加载到Ruby 中并在此处求和。现在,如果记录集真的很大,那么效率会明显降低,因为所有这些值都被加载到应用程序的内存中。

    编辑:添加 .compact - 这将在求和之前从数组中删除 nils(这会导致错误)。

    在 SQL 中执行此操作的建议方法是使用子查询,如下所示:

    SELECT SUM(subquery.column) FROM (
      SELECT * FROM models WHERE id = 5 LIMIT 3
    ) AS subquery;
    

    实际上并没有一种简单或直接的方法可以将其转换为 ActiveRecord 查询,因为这些查询希望从特定模型的表中进行选择。

    【讨论】:

    • 是的,这个方法终于奏效了! :) 但是如果数据不存在(= nil)对于限制中的某些值(例如,如果限制 = 30 并且只有 10 个值),'sum' 会引发错误,你知道如何解决这个“内联“?
    • @damoiser 要忽略 nil 值,请使用 .compact.sum 而不仅仅是 .sum
    【解决方案2】:

    您是否尝试以相反的方式编写查询?

    My_model.where(:id => id).order('date DESC').limit(X).sum(:column)
    

    这样,您已过滤模型以仅对缩小后的值求和。

    【讨论】:

    • 即使以这种方式,它也需要所有条目的总和。我也尝试将它存储在一个单独的变量中,然后进行求和但没有任何改变。我看到的唯一方法是手动迭代响应并手动求和值,但奇怪的是没有方法可以求和只有有限的 active_records 结果
    • 好吧,我找到了一种解决方法(日期 >= Z,其中 Z 是“30 天前”),但我没有解决问题。奇怪的是没有限制约束的可行解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 2021-10-22
    相关资源
    最近更新 更多