在聚合函数之前对ActiveRecord对象执行行操作

时间:2012-11-13 20:39:08

标签: ruby-on-rails ruby activerecord

我试图根据模型中的第二个变量计算模型中变量的加权平均值,而我却无法通过ActiveRecord找到一种方法。

class Employer < ActiveRecord::Base
  attr_accessible :name, :number_of_employees, :average_age

  def self.wt_avg_age
    #return sum(number_of_employee * average_age)/sum(number_of_employees)
  end
end 

在直接SQL中,我会使用:

SELECT id, SUM(number_of_employees*average_age)/SUM(number_of_employees) 
FROM employer
GROUP BY name    

我能否以一种雄辩的方式在ActiveRecord关系上执行类似的操作(即,不需要拉下单独的数组并迭代每条记录来获取我的分子)?我尝试过使用.select(),. pluck()和sum()的不同组合,没有任何运气。我无法获取ActiveRecord对象来执行sumproduct。

3 个答案:

答案 0 :(得分:1)

您应该可以执行以下操作:

Employer.select("name, (SUM(number_of_employees*average_age)/SUM(number_of_employees)) as sum").group(:name)

这会将Employer实例返回给您,但它们只有.name和.sum属性。这将运行您想要的确切SQL查询。

答案 1 :(得分:1)

看起来ActiveRecord::Calculations#sum需要一个块:

# File activerecord/lib/active_record/relation/calculations.rb, line 92
def sum(*args)
  if block_given?
    self.to_a.sum(*args) {|*block_args| yield(*block_args)}
  else
    calculate(:sum, *args)
  end
end

(另见http://api.rubyonrails.org/classes/Enumerable.html#method-i-sum

所以你可以试试:

def self.wt_avg_age
  numerator = self.all.sum { |e| e.number_of_employee * e.average_age }
  denominator = self.sum :number_of_employees
  return numerator / denominator
end

答案 2 :(得分:0)

试一试,也许它可行:

def self.wt_avg_age
  a = Employer.sum("number_of_employee * average_age")
  b = Employer.sum('number_of_employees')
  a/b
end