2010-11-24 56 views
1

嘗試使用Rails 2.3和MySQL以最有效的方式獲取某些報表的數據。Rails - 跨幾個關係有效地提取和計算數據

我們的應用有用戶,交易和購買交易。關係是這樣的:

class User 
    has_many :purchased_deals 
    has_many :deals, :through => :purchased_deals 
end 

class Deal 
    has_many :purchased_deals 
    has_many :users, :through => :purchased_deals 
end 

class PurchasedDeal 
    belongs_to :deal 
    belongs_to :user 
end 

對於我跑的報告,我需要的是已購買產品的所有用戶(即至少有一個PurchasedDeal),然後總和所有的交易,他們已購買(價格附於交易,而不是購買交易)。

當然,我可以從所有用戶的列表開始,包括交易和購買交易。我試過了,查詢量很大(30,000個用戶,有或沒有,3000個交易,100,000個以上的購買交易)。

我可以先從用戶開始,然後做一個.each並找到已購買交易的人,將他們分成他們自己的組,然後遍歷那些以獲得總購買金額,但這是相當多的查詢。

目前,這兩種方法都需要很長時間才能使請求超時。獲得我需要的數據最有效的方法是什麼?向列添加列是一個完全可以接受的解決方案,順便說一句。我有完整的數據庫訪問來做我需要的。

謝謝!

回答

0

要獲得用戶ID的列表與一個以上的購買,你可以做以下,這將只訪問一個表:

users = User.find user_ids 

user_ids = PurchasedDeal.count(:group => :user_id, :having => 'count_all > 0').keys 

隨後,您可以獲取所有這些用戶


事情可以加快與計數器緩存。在您的用戶模型中,將:counter_cache => true選項添加到購買交易的has_many關聯中。你會在你的用戶表需要一個額外的整數列和初始化,這可能看起來在遷移如下:

add_column :users, :purchased_deals_count, :integer, :null => false, :default => 0 
User.each { |u| User.reset_counters u, :purchased_deals } 

一旦這不礙事,就變成了簡單得多:

users = User.all :conditions => 'purchased_deals_count > 0' 

Rails將通過大多數標準操作使列保持最新狀態。


獲得總價將始終涉及加入。或者你可以建立一個交易價格的散列,並在Ruby中進行繁瑣的處理。我不是SQL專家,但是您可以通過將價格與PurchasedDeal一起存儲來消除連接。否則,這裏是如何與加盟做到這一點:

user_id_to_price = PurchasedDeal.sum 'deal.price', :include => :deal, :group => :user_id 

您可以通過添加類似:conditions => ['user_id IN (?)', users]篩選上你想要的用戶。(凡users可ID的列表,而且用戶對象)。

+0

當我嘗試運行您的第一條語句,它踢回MySQL錯誤關於「count_all」是一個未知的列。 – 2010-11-24 17:41:51

0

假設你添加的價格列purchased_deals表,你可以得到用戶和總的交易信息,價格是這樣的:

select users.id, sum(purchased_deals.price) from users, purchased_deals where users.id = purchased_deals.user_id group by users.id having sum(purchased_deals.price) > 0