Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 820
tbrooks Avatar asked Oct 22 '25 20:10

tbrooks


2 Answers

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.

like image 200
mu is too short Avatar answered Oct 25 '25 11:10

mu is too short


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)
like image 25
Edu Lomeli Avatar answered Oct 25 '25 10:10

Edu Lomeli