I\'m trying to list the number of users by age-range:
Range : #Users
10-14 : 16
15-21 : 120
22-29 : 312
30-40 : 12131
41-70 : 612
71-120 : 20
>
You want to build some SQL that looks like this:
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
In ActiveRecord terms, that would be:
# 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
That will leave you with an array of objects in age_ranges and those objects will have n and age_range methods. If you want a Hash out of that, then:
age_ranges = Hash[age_ranges.map { |r| [r.age_range, r.n] }]
That won't include ranges that don't have any people in them of course; I'll leave that as an exercise for the reader.