Pour obtenir une liste d'identifiants d'utilisateur avec plus d'un achat, vous pouvez procéder comme suit, ce qui n'accédera qu'à un seul tableau :
user_ids = PurchasedDeal.count(:group => :user_id, :having => 'count_all > 0').keys
Par la suite, vous pourrez récupérer tous ces utilisateurs avec :
users = User.find user_ids
Les choses peuvent être accélérées avec un contre-cache. Dans votre modèle utilisateur, ajoutez l'option :counter_cache => true
au has_many
association pour les offres achetées. Vous aurez besoin d'une colonne d'entiers supplémentaire sur votre table d'utilisateurs et d'initialisation, qui pourrait ressembler à ceci dans une migration :
add_column :users, :purchased_deals_count, :integer, :null => false, :default => 0
User.each { |u| User.reset_counters u, :purchased_deals }
Une fois cela réglé, cela devient beaucoup plus simple :
users = User.all :conditions => 'purchased_deals_count > 0'
Rails gardera la colonne à jour pour vous, avec la plupart des opérations standard.
Obtenir le prix total impliquera toujours une jointure. Ou vous pouvez créer un hachage des prix des transactions et effectuer le traitement fastidieux dans Ruby. Je ne suis pas un expert SQL, mais vous pouvez potentiellement vous débarrasser de la jointure en stockant le prix avec PurchasedDeal. Sinon, voici comment procéder avec une jointure :
user_id_to_price = PurchasedDeal.sum 'deal.price', :include => :deal, :group => :user_id
Vous pouvez filtrer cela uniquement sur les utilisateurs de votre choix en ajoutant quelque chose comme :conditions => ['user_id IN (?)', users]
. (Où les users
peut être une liste d'ID, mais aussi des objets Utilisateur.)