2011-11-11 127 views
7

我想同时做几聚合函数,如获得最大和最小的ID通过状态分组:如何在Rails/ActiveRecord中一次使用多个集合函数?

Model.maximum(:id).minimum(:id).group(:status) 

这不工作(至少使用Rails 3.1.1) - 你上了一个错误最低限度的通话,说它没有定义在Fixnum上。

NoMethodError: undefined method `minimum' for 22377:Fixnum 

我能为它做原料的SQL - 只是不知道是否有一个较高的水平/ Rails的选项...

谢谢,克里斯

回答

13

我相信@topek是正确的,你不能链的计算功能这样的。我认为你将不得不使用SQL在select谓词,例如:

Model.select('MAX(id) AS `maximum`, MIN(id) AS `minimum`').group(:status) 

我只是测试这在我自己的一个项目,它似乎按预期方式工作。

+1

这对我来说更好 - 很好。 –

3

我不认为这是可能的这些聚合函数,因为它们返回一个值而不是范围,请参阅docs。它们都使用的计算方法,正如你可以看到返回一个数字:

 # File lib/active_record/calculations.rb, line 117 
117:  def calculate(operation, column_name, options = {}) 
118:   validate_calculation_options(operation, options) 
119:   column_name  = options[:select] if options[:select] 
120:   column_name  = '*' if column_name == :all 
121:   column   = column_for column_name 
122:   catch :invalid_query do 
123:   if options[:group] 
124:    return execute_grouped_calculation(operation, column_name, column, options) 
125:   else 
126:    return execute_simple_calculation(operation, column_name, column, options) 
127:   end 
128:   end 
129:   0 
130:  end 

如果你想做到这一点,你必须制作手工查询。

下面是一个例子:

sql = "SELECT max(id) as max_id, 
       min(id) as min_id 
     FROM model 
     GROUP 
      BY status 
    " 
Model.find_by_sql(sql).each do |row| 
    puts "min. id: #{row.min_id}, " << 
     "max. id: #{row.max_id}, " 
end 
+0

OK-看起来不错,感谢。 –

12

我有一个类似的问题,我使用group Rails 4来解决问题。

Model.group(:status).pluck('min(id)','max(id)') 

也适用于有,排序等和计算列。

Model.group('CAST(created_at AS Date), EXTRACT(HOUR FROM created_at), floor(EXTRACT(MINUTE FROM created_at)/15) * 15') 
    .having('count(id) > 10') 
    .order('min(created_at)') 
    .pluck('count(id)') 

干杯

+0

谢谢,这个作品很棒。 – jayant

相关问题