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
scopesin yourModelfor repeatable query patterns. - NULLs: NULLs are grouped together, so handle them as per your needs.
- Having clause: Use the
havingmethod to filter grouped rows. Thewhereclause filters before aggregation whilehavingdoes 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
Modeland then run a query for each instance, leading to lots of unnecessary queries. Useincludesto load associated data in one hit. - Misinterpreted
count:countfetches the total rows—groupgives count per group, anddistinctcounts unique values.
Was this article helpful?