Group BY and COUNT using ActiveRecord
Create a field-frequency map with .group(:attribute).count
. Consider this example counting user roles:
Each key-value pair represents a role and the quantity of users under it.
SQL for humans, or ActiveRecord unveiled
Under the hood, ActiveRecord translates your queries into plain SQL. Our previous GROUP and COUNT operation:
Unveils this SQL equivalent:
The name
column from people
is grouped, and the count of each unique name is recorded. You get a neat hash mapping names to counts.
Census with joints, or mastering complex queries
Should your operation span across a few tables, lean on ActiveRecord
:
This petite yet potent line fetches the count of all orders neatly grouped by customer names. And all the join magic is performed unnoticed! The size
method here mimicks count
, but fits better when joining tables.
More data, more wisdom: .select() and .group()
Sometimes, more information is better:
Here, select
allows fetching specific columns. Thus, besides the name, you get its count (as 'name_count'). The result is still an ActiveRecord::Relation
, but each object carries both name and count.
One shot, all hit: Optimizing queries
Aim for efficiency in your queries. Grab all the data in a single call:
This serves you a list of people along with the count of their articles—in a single SQL query. The output has been already sorted for any further manipulations you plan.
The lonely distinct() function
If you just want to know how common an attribute is, go distinct
:
This would return the number of distinct names—not their counts. Remember, distinct
and group
are NOT interchangeable!
Be a Pro with Pro-tips:
- Scoping: Use custom ActiveRecord
scopes
in yourModel
for repeatable query patterns. - NULLs: NULLs are grouped together, so handle them as per your needs.
- Having clause: Use the
having
method to filter grouped rows. Thewhere
clause filters before aggregation whilehaving
does after it.
Gotchas and Pitfalls:
- Data greed: Don't select or group by columns you won't use—it makes your queries slower.
- N+1 trap: You fetch a
Model
and then run a query for each instance, leading to lots of unnecessary queries. Useincludes
to load associated data in one hit. - Misinterpreted
count
:count
fetches the total rows—group
gives count per group, anddistinct
counts unique values.
Was this article helpful?