2012-05-16 43 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以获得“实际操作”的完整解决方案。