tbrooks
tbrooks

Reputation: 85

Calculate Month Statistics

I have a donations table where I'm trying to calculate the total amount for each month. For months without without any donations, I'd like the result to return 0.

Here's my current query:

Donation.calculate(:sum, :amount, :conditions => { 
  :created_at => (Time.now.prev_year.all_year) }, 
  :order => "EXTRACT(month FROM created_at)", 
  :group => ["EXTRACT(month FROM created_at)"])

which returns:

{7=>220392, 8=>334210, 9=>475188, 10=>323661, 11=>307689, 12=>439889}

Any ideas how to grab the empty months?

Upvotes: 4

Views: 1495

Answers (2)

Edu Lomeli
Edu Lomeli

Reputation: 2282

In addition to mu is too short answer, in Rails 3.2.12 did not work for me, ActiveRecord returns the keys as strings:

h = Donation.calculate(:sum, :amount, :conditions => { 
    :created_at => (Time.now.prev_year.all_year) }, 
    :order => "EXTRACT(month FROM created_at)", 
    :group => ["EXTRACT(month FROM created_at)"])

Which returns:

{"7"=>220392, "8"=>334210, "9"=>475188, "10"=>323661, "11"=>307689, "12"=>439889}

So when I merge the hash with zeros:

{1=>0, 2=>0, 3=>0, 4=>0, 5=>0, 6=>0, 7=>0, 8=>0, 9=>0, 10=>0, 11=>0, 12=>0, "7"=>220392, "8"=>334210, "9"=>475188, "10"=>323661, "11"=>307689, "12"=>439889}

The little fix (to_s):

Hash[(1..12).map { |month| [ month.to_s, 0 ] }].merge(h)

Upvotes: 2

mu is too short
mu is too short

Reputation: 434665

Normally you'd left join to a calendar table (or generate_series in PostgreSQL) to get the missing months but the easiest thing with Rails would be to merge your results into a Hash of zeroes; something like this:

class Donation
  def self.by_month
    h = Donation.calculate(:sum, :amount, :conditions => { 
      :created_at => (Time.now.prev_year.all_year) }, 
      :order => "EXTRACT(month FROM created_at)", 
      :group => ["EXTRACT(month FROM created_at)"])
    Hash[(1..12).map { |month| [ month, 0 ] }].merge(h)
  end
end

then just call the class method, h = Donation.by_month, to get your results.

Upvotes: 5

Related Questions