按年龄范围分组用户在ruby中

我正在尝试按年龄范围列出用户数量:

Range : #Users 10-14 : 16 15-21 : 120 22-29 : 312 30-40 : 12131 41-70 : 612 71-120 : 20 

我在考虑创建一个静态的哈希数组:

 AGE_RANGES = [ {label:"10 - 14", min:10, max:14}, {label:"15 - 21", min:15, max:21}, {label:"22 - 29", min:22, max:29}, {label:"30 - 40", min:30, max:40}, {label:"41 - 70", min:41, max:70}, {label:"71 - 120", min:71, max:120} ] 

然后将其用于我的搜索filter以及我的查询。 但是,我想不出能从中获得最大性能的方法。

我的模型中的方法仅按年龄分组:

 def self.group_by_ageRange(minAge, maxAge) query = User.group("users.age") .where("users.age BETWEEN minAge and maxAge ") .select("users.age, count(*) as number_of_users") end 

有什么建议?

您想构建一些如下所示的SQL:

 select count(*), case when age between 10 and 14 then '10 - 14' when age between 15 and 21 then '15 - 21' -- ... end as age_range from users where age between 10 and 120 group by age_range 

在ActiveRecord术语中,这将是:

 # First build the big ugly CASE, we can also figure out the # overall max and min ages along the way. min = nil max = nil cases = AGE_RANGES.map do |r| min = [r[:min], min || r[:min]].min max = [r[:max], max || r[:max]].max "when age between #{r[:min]} and #{r[:max]} then '#{r[:min]} - #{r[:max]}'" end # Then away we go... age_ranges = Users.select("count(*) as n, case #{cases.join(' ')} end as age_range") .where(:age => min .. max) .group('age_range') .all 

这将为您提供age_ranges一组对象,这些对象将具有nage_range方法。 如果你想要哈希,那么:

 age_ranges = Hash[age_ranges.map { |r| [r.age_range, rn] }] 

那当然不包括那些没有任何人的范围; 我将把它作为读者的练习。

我发现接受的答案有点密集。 快速但难以理解和写作。 今天,我想出了一个更慢但更简单的解决方案。 由于我们将年龄分组到范围内,我们可以假设我们的值不会超过125

这意味着如果在分组和计数结果集上使用rubyfilter,则不会迭代超过125个项目。 这将比基于sql范围的组/计数慢,但它对于我的目的来说足够快,同时仍然依赖于DB来完成大部分繁重的工作。 迭代少于125项的哈希似乎不是什么大问题。 特别是当键值对只是这样的内联:

 { 0 => 0, 1 => 1, 3 => 5, 25 => 3, 99 => 3 } 

这是psudo代码:

 users = User .where(age: (min..max)) .group(:age) .count(:age) group = Hash.new(0) users.each{|age, count| case when age <= 10 group['under 10'] += count when age <= 25 group['11-25'] += count when age <= 40 group['26-40'] += count else group['41+'] += count end } 

注意:此解决方案提供给定范围内的用户数。