Сортировать по рефереру (довольно сложно) - PullRequest
1 голос
/ 24 августа 2010

Я сделаю все возможное, чтобы быть кратким и полностью объяснительным в этом затруднительном положении.

На сайте, которым я управляю, мы позволяем менеджеру просматривать их "Рекрутинг Downline", который включает в себя список всех агентов, которых они наняли лично, а также рекрутов, которых этот конкретный агент (и так далее, и так далее) привел к Команда.

Например:

  • Я набираю двух агентов, А и В.
  • А набирает двух агентов, С и D.
  • B набирает двух агентов, E и F.
  • D набирает двух агентов G и H.
  • C, E и F ничего не делают.

alt text

В базе данных каждая запись об отдельном агенте имеет поле для «ссылающегося агента», в котором указывается набранный агент.

  • Как верхний уровень, когда я нажимаю «Мой Новобранцы ", мне показывают список всех субагенты (потому что они ВСЕ падают под моим зонтиком).
  • A может просматривать C, D, G и H.
  • B может видеть только E и F как они его единственные новобранцы и они никого не привели на доска.

Хотя эта функциональность работает отлично, она имеет недостатки по двум причинам:

Из-за особенностей построения наших PHP-скриптов мы не можем отсортировать данные уровня комиссии в целом. Пример: даже когда мы с топ-менеджером видим всех, сортировка по «уровню комиссии» сортирует моих непосредственных агентов по критериям, затем их нижестоящий элемент как элемент, а затем продолжает сортировку на основе моих критериев. Это трудно понять, поэтому для демонстрации предположим, что в таблице ниже показан «уровень комиссии» для ВСЕХ агентов:

  • А, 7
  • B, 6
  • С, 5
  • Д, 6
  • E, 5
  • F, 2
  • G, 5
  • Н, 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 зависит от номера прямого агента, который определяет, кто будет следующим в строке.

Я понимаю, что это "очень" трудно понять, но дайте мне знать, если я смогу дать какое-либо дополнительное понимание нашей текущей проблемы "сортировки".

Ответы [ 3 ]

1 голос
/ 24 августа 2010

я думаю, что понял тебя.Вы хотите отсортировать по параметру 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);
*/
1 голос
/ 24 августа 2010

Звучит так, будто вы пытаетесь реализовать древовидные структуры в вашей БД.Рассматривали ли вы вопрос об использовании деревьев Celko:

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

Лично я бы хотел реализовать большую часть порядка, выбирая аспекты этого типа проекта в БД.Обратите внимание, что деревья Celko не очень подходят для очень больших наборов данных.

0 голосов
/ 24 августа 2010

Итак, проблема в том, что вы не храните «уровень комиссии» (который я считаю количеством узлов, расстояние которых <∞) в базе данных? </p>

У вас есть два варианта:

  • Измените схему, чтобы ее можно было легко найти. См. эту статью .
  • Если это не вариант, вычисление его с использованием только SQL в MySQL может оказаться невозможным, поскольку у вас нет итеративных запросов (предложение WITH RECURSIVE) Вы должны сделать несколько запросов в PHP.
...