Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I count the result of an ActiveRecord .group query? Chaining .count returns a hash

I can use the following :

User.where("zip_code = '48104'").group('users.id').count

To get hashes like :

{195=>1, 106=>1, 120=>1, 227=>1, 247=>1, 264=>1, 410=>1}

Is there a way I can count these hashes, and just return 7, instead of the above result ?

I know this doesn't make sense in the above scenario, and I can just do it by not using the group clause. But I'm working on a more complex query, where I need to implement this. Thanks in advance.

like image 323
Myxtic Avatar asked Sep 05 '12 14:09

Myxtic


People also ask

What is ActiveRecord in Ruby on Rails?

What is ActiveRecord? ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.

What is an ActiveRecord relation?

An instance of ActiveRecord::Base is an object that represents a specific row of your database (or might be saved into the database). Whereas an instance of ActiveRecord::Relation is a representation of a query that can be run against your database (but wasn't run yet).

What is eager loading in rails?

There are actually three ways to do eager loading in Rails. use preload() to fetch the data with a separate db query (just one though, avoiding N+1 queries) use eager_load() to fetch data with one large query and an outer join. use includes() to dynamically find the best solution and preload or eager load the data.


2 Answers

Try:

User.where("zip_code = '48104'").group('users.id').count.length
like image 177
robbrit Avatar answered Oct 01 '22 05:10

robbrit


The accepted answer is not scalable. Using @robbrit's method on a query with 25,000 matching users would pull 25,000 results (ie an array with 25,000 elements) into memory and then count the elements array. Here is a method that will do it without pulling all that data:

def count_query(query)
  query = "SELECT count(*) AS count_all FROM (#{query.to_sql}) x"
  ActiveRecord::Base.connection.execute(query).first.try(:[], 0).to_i
end

It is used like this:

query = User.where("zip_code = '48104'").group('users.id')
count = count_query(query)

This works for me using mysql, btw.

It was inspired by this guy: https://github.com/mrbrdo/active_record_group_count/blob/master/lib/active_record_group_count/scope.rb

like image 37
orourkedd Avatar answered Oct 01 '22 05:10

orourkedd