2012-05-16 35 views
3

一個人得到10%的轉介,以便他的推薦朋友進行購買。mysql查詢生成基於被推薦成員的調查報告

有兩個表:

  1. 參考表
  2. 事務表

參考表

Person_id Referrer_id 
3    1 
4    1 
5    1 
6    2 

事務表

Person_id Amount  Action  Date 
    3   100  Purchase 10-20-2011 
    4   200  Purchase 10-21-2011 
    6   400  Purchase 12-15-2011 
    3   200  Purchase 12-30-2011 
    1   50  Commision 01-01-2012 
    1   10  Cm_Bonus 01-01-2012 
    2   20  Commision 01-01-2012 

如何得到以下結果集爲Referrer_Person_id = 1

Month  Ref_Pur Earn_Comm Todate_Earn_Comm BonusRecvd Paid Due 
10-2011 300  30   30     0   0  30 
11-2011  0  0   30     0   0  30 
12-2011 200  20   50     0   0  50 
01-2012  0  0   50     10   50  0 


上面使用的標籤是:

Ref_Pur   = Total Referred Friend's Purchase for that month 

Earn_Comm  = 10% Commision earned for that month 

Todate_Earn_Comm = Total Running Commision earned upto that month 

MySQL的代碼,我寫

SELECT dx1.month, 
     dx1.ref_pur, 
     dx1.earn_comm, 
     (@cum_earn := @cum_earn + dx1.earn_comm) as todate_earn_comm 

FROM 

(
    select date_format(`date`,'%Y-%m') as month, 
      sum(amount) as ref_pur , 
      (sum(amount)*0.1) as earn_comm 
    from transaction tr, reference rf 
    where tr.person_id=rf.person_id and 
      tr.action='Purchase' and 
      rf.referrer_id=1 
    group by date_format(`date`,'%Y-%m') 
    order by date_format(`date`,'%Y-%m') 

)as dx1 

JOIN (select @cum_earn:=0)e; 

如何加入 該查詢還包括BonusRecvd,Paid和Due trnsactions,它不依賴於參考表?

,並生成行月'11 -2011' ,即使沒有發生trnx上月

+0

@chris我試過的一個可以顯示ref_pur,Earn_comm,Todate_Earn_Comm,但不能包括BonusRecvd,付費和到期。 –

+0

@chris因爲當月沒有trnx發生,所以'11 -2011'月也無法生成行 –

+0

你能發佈你的代碼嗎? –

回答

1

如果要包括佣金和獎金到結果,你可能需要包括相應的行(Action IN ('Commision', 'Cm_Bonus'))轉換爲您用來計算結果的初始數據集。或者,至少,這就是我會做,它可能是這樣的:

SELECT t.Amount, t.Action, t.Date 
FROM Transaction t LEFT JOIN Reference r ON t.Person_id = r.Person_id 
WHERE r.Referrer_id = 1 AND t.Action = 'Purchase' 
    OR t.Person_id = 1 AND t.Action IN ('Commision', 'Cm_Bonus') 

而且每月計算時的SUM,您可以使用CASE表達式涉及到不同的充類型的Action量之間進行區分。這是怎麼查詢的相應部分可能看起來像:

… 
IFNULL(SUM(CASE Action WHEN 'Purchase' THEN Amount END)  , 0) AS Ref_Pur, 
IFNULL(SUM(CASE Action WHEN 'Purchase' THEN Amount END) * 0.1, 0) AS Earn_Comm, 
IFNULL(SUM(CASE Action WHEN 'Cm_Bonus' THEN Amount END)  , 0) AS BonusRecvd, 
IFNULL(SUM(CASE Action WHEN 'Commision' THEN Amount END)  , 0) AS Paid 
… 

在計算Due值,可以初始化另一個變量,並用它非常類似於@cum_earn,除非你還需要減去Paid,東西像這樣:

(@cum_due := @cum_due + Earn_Comm - Paid) AS Due 

最後一個問題似乎失蹤了幾個月。爲了解決這個問題,我會做到以下幾點:

  1. 拿到第一,從子集的最後日期的處理方式(如通過查詢在文章的開頭獲得)。

  2. 獲取每個日期的相應月份(即僅僅是同一月份的第一個日期)。

  3. 使用數字表,生成覆蓋上一步計算的兩個月的列表。

  4. 過濾出要處理的子集中存在的月份,並使用剩餘的月份將虛擬事務添加到子集。

正如您所看到的,執行這些步驟時需要觸摸兩次「要處理的子集」。因此,爲了提高效率,我會將該子集插入臨時表並使用該表,而不是多次執行相同的(子)查詢。

步驟#3中提到的數字表是我建議始終保持方便的工具。你只需要初始化一次,如果你饒恕雙關,那麼它的用途可能會變得很多。以下是填充數字表的一種方法:

CREATE TABLE numbers (n int); 
INSERT INTO numbers (n) SELECT 0; 
INSERT INTO numbers (n) SELECT cnt + n FROM numbers, (SELECT COUNT(*) AS cnt FROM numbers) s; 
INSERT INTO numbers (n) SELECT cnt + n FROM numbers, (SELECT COUNT(*) AS cnt FROM numbers) s; 
INSERT INTO numbers (n) SELECT cnt + n FROM numbers, (SELECT COUNT(*) AS cnt FROM numbers) s; 
INSERT INTO numbers (n) SELECT cnt + n FROM numbers, (SELECT COUNT(*) AS cnt FROM numbers) s; 
INSERT INTO numbers (n) SELECT cnt + n FROM numbers, (SELECT COUNT(*) AS cnt FROM numbers) s; 
INSERT INTO numbers (n) SELECT cnt + n FROM numbers, (SELECT COUNT(*) AS cnt FROM numbers) s; 
INSERT INTO numbers (n) SELECT cnt + n FROM numbers, (SELECT COUNT(*) AS cnt FROM numbers) s; 
INSERT INTO numbers (n) SELECT cnt + n FROM numbers, (SELECT COUNT(*) AS cnt FROM numbers) s; 
/* repeat as necessary; every repeated line doubles the number of rows */ 

而且似乎是這樣。我不會在這裏發佈一個完整的解決方案,以免您有機會嘗試以您自己的方式使用上述建議,以防您非常喜歡。但是如果您正在努力或者只是想驗證他們是否可以將應用於所需的效果,則可以嘗試this SQL Fiddle page以獲得「實際操作」的完整解決方案。