Как пройти вверх через MySQL подготовленный оператор для расчета иерархических комиссий - PullRequest
2 голосов
/ 23 декабря 2010

Обновление **:

Я изменил название вопроса, чтобы лучше соответствовать общей потребности.В настоящее время у меня есть одна таблица с идентификаторами моих продавцов, соответствующими родительскими идентификаторами, уровнем комиссионных, суммой проданных продуктов и общей комиссией за эти продукты (рассчитывается в выписке по делу, поскольку комиссии зависят от продукта);но проблема, с которой я продолжаю сталкиваться, заключается в следующем:

Я не могу затем пересечь результаты моего запроса и вычислить подкомиссии, которые каждый продавец должен получить в результате своих нижестоящих продавцов (продавцов, которых они имеютвзято на борт на уровнях комиссионных ниже них).


Исходное сообщение:

У меня есть скрипт, который в настоящее время «работает», но содержит почти 3600 строк кода и выполняет более 50 вызовов базы данных в одном скрипте.Исходя из моего опыта, невозможно по-настоящему «зациклить» сценарий и свести его к минимуму, потому что каждый вызов базы данных является подзапросом запросов, основанных на идентификаторах рефералов.

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

В моем примере есть три таблицы:

Таблица 1 - Продавцы

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

Если ID - это идентификатор одного из наших торговых агентов, comm_level будет определять процент его комиссионного вознаграждения за каждый продукт, который он продает, а родительский - идентификатор, для которого был набран конкретный агент.В приведенном выше примере 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, он получит50% на каждый проданный предмет 1, 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

Эта таблица объединяет действительныеТовар продан продавцу, который продал товар.

При создании отчета о комиссии рассчитать отдельные значения очень просто. Однако рассчитать комиссию на основе их суб_продавцов очень сложно.

В этом примере, Продавец с идентификатором 1 получает часть каждого проданного товара. Процент комиссии указывает на индивидуальные продажи или размер их комиссии.

Например:

Когда продавец с идентификатором 6 продал один из пунктов item_2 выше, дерево комиссионных будет выглядеть следующим образом:

-ID 6 - 25% от стоимости (item_1)

-ID 3 - 5% стоимости (item_1) - (30% его комм. - 25% комм. продавца id 6)

-ID 1 - 10% стоимости (item_1) - (40% его комм. - 30% отИдентификатор продавца 3)

Это должно быть рассчитано для каждого агента в системе сверху вниз (следовательно, БД вызывает внутри while, повторяя весь мой огромный сценарий).

У кого-нибудь есть хорошее предложение или образцы, которые он, возможно, использовал в прошлом?

РЕДАКТИРОВАТЬ В СТРУКТУРУ КОМИССИИ

Примечание: комиссии в этом примере являются остаточными, то есть если продавецНачиная с 1 месяца, он / она будет получать такую ​​же комиссию для этого клиента, пока он не перестанет быть подписчиком.

Ответы [ 2 ]

1 голос
/ 23 декабря 2010

это может помочь вам начать ...

-- 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());
1 голос
/ 23 декабря 2010

Используйте абстракции (функции и классы), чтобы скрыть доступ к базе данных. Это позволяет быть более лаконичным при написании алгоритма расчета комиссий. Кроме того, он позволяет повторно использовать результаты предыдущих запросов к базе данных. В конце концов, одного цикла по таблице «Проданные товары» должно быть достаточно, заполняя комиссии фактического продавца и всех предков. В идеале каждый продавец будет считываться из базы данных только один раз, либо сразу, либо на лету.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...