如何横向向上通过MySQL准备语句来计算层次结构委员会

时间:2010-12-23 17:50:16

标签: php mysql pdo

更新**:

我改变了问题的标题,以更好地满足整体需求。我目前有一张表,其中包含我的卖家ID,他们各自的父母ID,他们的佣金水平,他们销售的产品总数以及这些产品的总佣金(在案例陈述中计算,因为佣金因产品而异);但我继续遇到的问题是:

我无法横向查询我的查询结果并计算每个卖家应该收到的子佣金,这是因为他们的下线卖家(他们已经将佣金水平低于他们的卖家)。




原帖:

我有一个目前“有效”的脚本,但是有近3600行代码,并且在一个脚本中完成了超过50个数据库调用。根据我的经验,没有办法真正“循环”脚本并最小化它,因为每次调用数据库之前都是基于引用ID的子查询。

也许我可以给出一个非常简单的例子,说明我想要完成什么,看看是否有人有类似的经历。

在我的例子中,有三个表:

表1 - 卖方

ID       |   Comm_level   |   Parent
-----------------------------------
1        |        4       |   NULL
2        |        3       |   1
3        |        2       |   1
4        |        2       |   2
5        |        2       |   2
6        |        1       |   3

如果ID是我们的某个销售代理商的ID,则comm_level将确定他销售的每种产品的佣金百分比,父母表示招募该特定代理商的ID。 在上面的例子中,1是最高级代理人,他招募了两名代理人,2名和3名.2名招募了两名代理人,4名和5名.3名招募了一名代理人,6名。注意:代理人不得招募任何等于或高于他们的人。自己的水平。

表2 - 佣金

Level    |    Item 1    |     Item 2     |    Item 3
-----------------------------------------------------
4        |      .5      |       .4       |      .3    
3        |      .45     |       .35      |      .25    
2        |      .4      |       .3       |      .2    
1        |      .35     |       .25      |      .15 

此表根据实际的comm_level列出每个代理商的佣金百分比(如果代理商处于4级,他将在每件商品1上获得50%,在每件商品上获得40%2,每个商品获得30%第3项等等。

表3 - 已售物品

      ID     |      Item
   ---------------------
       4     |     item_1
       4     |     item_2
       1     |     item_1
       2     |     item_3
       6     |     item_2
       1     |     item_3

此表格将售出的实际商品与销售商品的卖家配对。

生成佣金报告时,计算个别值非常简单。然而,根据子经销商计算佣金非常困难。

在此示例中,卖家ID 1获得每件商品的一部分。佣金百分比表示个人销售额或佣金高度。

例如:

当卖家ID 6卖出上述第2项之一时,佣金树将如下所示:

-ID 6 - 成本的25%(item_1)

-ID 3 - 成本的5%(item_1) - (30%是他的通讯 - 卖家ID 6的25%通讯)

-ID 1 - 成本的10%(item_1) - (40%是他的通讯 - 卖家ID 3的30%)

这必须从上到下为系统中的每个代理计算(因此在我的庞大脚本中,while循环中的DB调用)。

过去有人提出过很好的建议或样本吗?

编辑委员会结构

注意:此示例中的佣金是剩余的,这意味着如果卖方在第1个月登上客户,他/她将收到该客户的相同佣金,直到他们不再是订户为止。

2 个答案:

答案 0 :(得分:1)

使用抽象(函数和类)来隐藏数据库访问。这使您在编写计算佣金的算法时更加简洁。此外,它允许您重用早期数据库查询的结果。最后,物品售出表上的一个循环应该足够,填写实际卖家和所有祖先的佣金。理想情况下,每个卖家只能在数据库中读取一次,无论是在前面还是在运行中。

答案 1 :(得分:1)

这可能有助于您入门......

-- TABLES

drop table if exists seller;
create table seller
(
seller_id int unsigned not null auto_increment primary key,
comm_level tinyint unsigned default 0,
parent_seller_id int unsigned default null,
key (parent_seller_id)
)
engine = innodb;

insert into seller (comm_level, parent_seller_id) values
(4,null),
 (3,1),
 (2,1),
    (2,2),
    (2,2),
        (1,3);

-- STORED PROCEDURES

drop procedure if exists seller_commissions_hier;
delimiter #

create procedure seller_commissions_hier
(
in p_seller_id int unsigned,
in p_start_date date,
in p_end_date date
)
proc_main:begin

declare done tinyint unsigned default 0;
declare dpth smallint unsigned default 0;

drop temporary table if exists hier;
drop temporary table if exists tmp;

create temporary table hier(
 parent_seller_id int unsigned, 
 seller_id int unsigned not null, 
 depth smallint unsigned not null default 0,
 comm_level tinyint unsigned not null default 0,
 sales decimal(10,2) not null default 0,
 commission decimal(10,2) not null default 0
)
engine = memory;

-- step1. work out the hierarchy with sales and commission set to 0

insert into hier select parent_seller_id, seller_id, 0, comm_level, 0 as sales, 0 as commission
 from seller where seller_id = p_seller_id;

/* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */

create temporary table tmp engine=memory select * from hier;

while not done do

    if exists( select 1 from seller s inner join hier on s.parent_seller_id = hier.seller_id and hier.depth = dpth) then

        insert into hier 
            select s.parent_seller_id, s.seller_id, dpth + 1, s.comm_level, 0, 0 from seller s
            inner join tmp on s.parent_seller_id = tmp.seller_id and tmp.depth = dpth;

        set dpth = dpth + 1;            

        truncate table tmp;
        insert into tmp select * from hier where depth = dpth;

    else
        set done = 1;
    end if;

end while;

-- step 2. update the hier table with sales totals for period you are interested in for each seller (to do)

-- (hint: use a derived table to calculate total sales for period grouped by seller_id and join back to hier for the update)

-- step 3. work out commissions based on sales and comm_level for each seller (to do)

-- (sure you can work this out)

-- step 4. output the results

select 
 s.seller_id,
 p.seller_id as parent_seller_id,
 hier.depth,
 hier.comm_level,
 hier.sales,
 hier.commission
from 
 hier
inner join seller s on hier.seller_id = s.seller_id
left outer join seller p on hier.parent_seller_id = p.seller_id
order by
 hier.depth, hier.seller_id; 

drop temporary table if exists hier;
drop temporary table if exists tmp;

end proc_main #

delimiter ;

-- TESTING

call seller_commissions_hier(1, now() - interval 1 month, now());

call seller_commissions_hier(2, now() - interval 1 month, now());