2011-06-14 32 views
0

在Rails 3(也有,如果你覺得在你的查詢中使用它meta_where寶石),我得到了我一直在敲打我的頭一個真正棘手的查詢:整蠱Rails3中/ MySQL查詢

假設我有兩個模型,顧客和購買,顧客有很多購買。讓我們將至少有兩件購物的顧客定義爲「repeat_customer」。我需要每天找repeat_customers總數在過去的3個月,是這樣的:

Date TotalRepeatCustomerCount 
1/1/11 10 (10 repeat customers by the end of 1/1/11) 
1/2/11 15 (5 more customer gained "repeat" status on this date) 
1/3/11 16 (1 more customer gained "repeat" status on this date) 
... 
3/30/11 150 
3/31/11 160 

基本上我需要根據創建自己的第二次購買之日起集團客戶數,因爲這是當他們「獲得重複地位」。

當然,這可以用Ruby實現,是這樣的:

Customer.includes(:purchases).all.select{|x| x.purchases.count >= 2 }.group_by{|x| x.purchases.second.created_at.to_date }.map{|date, customers| [date, customers.count]} 

然而,上面的代碼將火上Customer.allPurchase.all相同的路線查詢,然後做了一堆計算的紅寶石。我更喜歡在mysql中進行選擇,分組和計算,因爲它不僅速度更快,而且還減少了數據庫中的帶寬。在大型數據庫中,上面的代碼基本上是無用的。

我一直在嘗試一段時間來召喚rails/active_record中的查詢,但即使使用meta_where gem也沒有運氣。如果必須的話,我也會接受純粹的mysql查詢解決方案。

編輯:我會緩存它(或添加一個「重複」字段給客戶),雖然只是爲了這個簡化的問題。客戶在任何時候都可以改變重複客戶的標準(2次購買,3次購買,4次購買等),所以不幸的是我不得不在現場進行計算。

+0

您是否可以創建一張緩存此信息並在購買時生成該信息的表格。這樣就沒有計算開銷,你只需要爲用戶計算一次狀態。 – 2011-06-14 01:19:53

+0

這並不直接回答,但爲了擴展Devin的評論,您可以向客戶添加一個名爲repeat_status_date的列,並在購買對象上使用after_save回調進行編寫。 – 2011-06-14 01:44:53

+0

我會緩存它(或爲客戶添加一個「重複」字段),但僅限於此簡化問題。客戶在任何時候都可以改變重複客戶的標準(2次購買,3次購買,4次購買等),所以不幸的是我不得不在現場進行計算。 – Charles 2011-06-14 17:19:59

回答

0
SELECT p_date, COUNT(customers.id) FROM 
(
    SELECT p_date - INTERVAL 1 day p_date, customers.id 
    FROM 
    customers NATURAL JOIN purchases 
    JOIN (SELECT DISTINCT date(purchase_date) p_date FROM purchases) p_dates 
    WHERE purchases.purchase_date < p_date 
    GROUP BY p_date, customers.id 
    HAVING COUNT(purchases.id) >= 2 
) a 
GROUP BY p_date 

我沒有絲毫的測試,所以我希望它的作品。另外,我希望我能理解你正在努力完成的事情。

但請注意,你不應該這樣做,它會太慢。由於數據在一天過去之後永遠不會改變,因此每天只需緩存一次。

+0

我會緩存它(或爲客戶添加「重複」字段),但僅限於此簡化問題。客戶在任何時候都可以改變重複客戶的標準(2次購買,3次購買,4次購買等),所以不幸的是我不得不在現場進行計算。 – Charles 2011-06-14 17:19:50

+0

如果此代碼能夠正常工作,很高興收到回覆。 – Ariel 2011-06-15 06:57:40