mysql查询根据引用的成员生成佣金报告

时间:2012-05-16 10:52:18

标签: mysql sql select group-by

一个人因其推荐的朋友的购买而获得10%的佣金。

有两个表:

  1. 参考表
  2. 交易表
  3. 参考表

    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

    的以下Resultset
    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

1 个答案:

答案 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. 过滤掉要处理的子集中存在的月份,并使用剩余的月份将虚拟交易添加到子集中。

  5. 如您所见,执行这些步骤时需要触摸两次“要处理的子集”。因此,为了有效,我会将该子集插入临时表并使用该表,而不是多次执行相同(子)查询。

    步骤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以获得“实际行动”的完整解决方案。