views:

38

answers:

2

Hi there,

I have the following tables:

User :has_many Purchases
Item :has_many Purchases

Item has a column "amount" (can be + or -) and I need to find all Users that have a positive SUM of "Item.amounts" (over all Purchases each one has made).

How does this query look like? (I'm not sure how to handle "SUM" correctly, in this case.)

I started out with the following, but obviously, it's wrong... (it wouldn't "include" Purchases that have an Item with a negative Item.amount...)

@users = User.find(:all,
:include => {:purchases => :item},
:select => "SUM(item.amount)",
:order => "...",
:conditions => "...",
:group => "users.id",
:having => "SUM(item.amount) > 0" )

Thanks for your help with this!
Tom

A: 

It sounds like this is a good case for some model methods.

I didn't test this but I think you want to do something similar to the following:

class User < ActiveRecord::Base

has_many :purchases
has_many :items, :through => :purchases

def items_total
  #get all the items iterate over them to get the amount, 
  #compact to get rid of nils
  #and reduce with a sum function to total and return
  items.all.each{|item| item.amount}.compact.reduce(:+)
end

then

User.items_total

Jed Schneider
Thanks, but if I'm not mistaken, there seems to be a misunderstanding: Your solution seems to return a sum (I actually need the Users for the mentioned "conditions").Btw, I've never come across ".reduce(:+)" - any idea where I can find the documentation for this one?
TomDogg
yes, you are right, i thought you were looking for the total of the items for a user, in a 'grand total' type of context. reduce(:+) is a shorthand for reduce{|sum, i| sum+i} which basically sums all the items in a collection. http://apidock.com/ruby/Enumerable/reduce
Jed Schneider
Cool, thanks a bunch!
TomDogg
A: 

Try this:

User.all(:joins => items, :group => "users.id", 
          :having => "SUM(items.amount) > 0")
KandadaBoggu
Thanks - that works as needed!1 question back: what's the explanation that it works with ":joins" but not with ":include"?
TomDogg
The `:include` clause uses `LEFT OUTER JOIN`, which results in NULL amounts for users without items. The SUM function does not like NULL. Apart from this, in this situation `:joins` is more appropriate than `:include`.
KandadaBoggu
Great, thanks a lot !
TomDogg