按推荐人排序(相当复杂)

时间:2010-08-23 20:55:49

标签: php mysql sorting hierarchy

我将尽力在这种困境中既简洁又完全解释。

在我管理的网站上,我们允许经理查看他们的“招募下线”,其中包含他们个人招募的所有代理商的列表,以及特定代理商(等等)带来的新员工。球队。

例如:

  • 我招募了两名特工A和B.
  • A招募两名代理人,C和D.
  • B招募两名代理人,E和F.
  • D招募两名代理人G和H.
  • C,E和F什么都不做。

alt text

在数据库中,每个代理记录都有一个“推荐代理人”字段,其中列出了他们的招募代理人。

  • 作为顶级,当我点击“我的 新兵“,我看到了所有人的清单 子代理人(因为他们全都堕落了 在我的保护伞下)。
  • A能够查看C,D,G和H.
  • B只能查看E和F. 他们是他唯一的下线新兵 他们没有带来任何人 板。

虽然这个功能很有效,但它存在缺陷有两个原因:

由于构建PHP脚本的方式,我们无法整体调整佣金级别数据。示例:即使作为顶级人员和我可以看到所有人,按“佣金级别”排序按标准对我的直接代理进行排序,然后将其下线作为项目,然后根据我的标准继续排序。这很难理解,为了证明这一点,假设下表显示了所有代理商的“佣金水平”:

  • A,7
  • B,6
  • C,5
  • D,6
  • E,5
  • F,2
  • G,5
  • H,1

注意:代理人永远不能在比他们所处的更高级别招募另一名代理人,但他们可以在他们以下的任何级别招募(例如,7人可以在1,2,3,4,5,6招募,而3人可以只招募1,2)。

从我的(高级别)角度来看,

虽然将数据“按佣金水平排序”是有意义的: A,D,B,G,C,E,F,H - 情况并非如此。

相反(从顶级经纪人的角度来看,请注意): A,D,G,H,C,B,E,F

基本上,每个while循环都依赖于DIRECT上线代理号来确定谁下一个排队。

我理解这是“非常”难以理解,但如果我能对我们当前的“排序”问题提供任何其他理解,请告诉我。

3 个答案:

答案 0 :(得分:1)

听起来你正试图在数据库中实现树状结构。你考虑过使用Celko树吗?

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

就个人而言,我希望实现大部分订购,在数据库中选择此类项目的各个方面。请注意,Celko树不适合非常大的数据集。

答案 1 :(得分:1)

我认为我了解你。您希望按给定代理程序层次结构中的commission_level进行排序。以下内容可能有所帮助(http://pastie.org/1111097

drop table if exists agent;

create table agent
(
agent_id int unsigned not null auto_increment primary key,
name varchar(32) not null,
commission_level tinyint unsigned default 0,
parent_agent_id int unsigned default null
)
engine = innodb;

insert into agent (name, commission_level, parent_agent_id) values

('I', 99, null),
  ('A', 7, 1),
  ('B', 6, 1),
    ('C', 5, 2),
    ('D', 6, 2),
    ('E', 5, 3),
    ('F', 2, 3),
      ('G', 5, 5),
      ('H', 1, 5);


delimiter ;

drop procedure if exists agent_hier;

delimiter #

create procedure agent_hier
(
in p_agent_id int unsigned
)
proc_main:begin

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


create temporary table hier(
 parent_agent_id int unsigned, 
 agent_id int unsigned, 
 depth smallint unsigned default 0
)engine = memory;

insert into hier values (p_agent_id, p_agent_id, dpth);

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

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

while done <> 1 do

    if exists( select 1 from agent a inner join hier on a.parent_agent_id = hier.agent_id and hier.depth = dpth) then

        insert into hier 
            select a.parent_agent_id, a.agent_id, dpth + 1 from agent a
            inner join tmp on a.parent_agent_id = tmp.agent_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;


select 
 a.agent_id,
 a.name as agent_name,
 if(a.agent_id = b.agent_id, null, b.agent_id) as parent_agent_id,
 if(a.agent_id = b.agent_id, null, b.name) as parent_agent_name,
 hier.depth,
 a.commission_level
from 
 hier
inner join agent a on hier.agent_id = a.agent_id
inner join agent b on hier.parent_agent_id = b.agent_id
order by
 -- dont want to sort by depth but by commision instead - i think ??
 -- hier.depth, hier.agent_id; 
 a.commission_level desc;

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

end proc_main #


delimiter ;


/*

select * from agent;

call agent_hier(1);
call agent_hier(2);
call agent_hier(3);
call agent_hier(5);
*/

答案 2 :(得分:0)

所以问题是你没有在数据库中存储“佣金级别”(我认为它是距离<∞的节点数)?

您有两种选择:

  • 更改您的架构,以便轻松检索。见this article
  • 如果不能选择仅在MySQL中使用SQL计算它,则可能无法实现,因为您没有迭代查询(WITH RECURSIVE子句)。您必须在PHP中进行多个查询。