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
I was thinking of creating a static array of hashes:
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}
]
and then use it for my search filter, as well as for my query. But, I cannot think of a way of getting the most performance out of it.
My method in my model only groups by age:
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
Any suggestions?
You want to build some SQL that looks like this:
In ActiveRecord terms, that would be:
That will leave you with an array of objects in
age_ranges
and those objects will haven
andage_range
methods. If you want a Hash out of that, then: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.
I find the accepted answer to be a bit dense. Fast but hard to understand and write. Today, I came up with a slower but simpler solution. Since we are grouping ages into ranges, we can assume that we won't have values over 125
That means that if you use a ruby filter on a grouped and counted result set, you won't iterate over more than 125 items. This will be slower than a sql range based group/count, but it was fast enough for my purposes while still relying on the DB for most of the heavy lifting. Iterating over a hash with less than 125 items doesn't seem like a big deal. Especially when the key value pairs are just ints like this:
Here's the psudo-code:
Note: this solution provides the count of users in a given range.