2013-12-16 2 views
2

Рассмотрим таблицу, содержащую 3 DiscountPrograms, с присвоенной порядка расчетаКак рассчитать каскадный сценарий скидок продаж с использованием TSQL?

create table program (programid varchar(5), calc_order tinyint) 

go 

insert tblprogram(programid, calc_order) 
values(prog1, 1) 

insert tblprogram(programid, calc_order) 
values(prog2, 2) 

insert tblprogram(programid, calc_order) 
values(prog3, 3) 

go 

... и таблица продуктов, которые присваивается программировать

create table tblproduct(productid varchar(11), programid varchar(5)) 

go 

insert tblproduct(productid, programid) 
values(productabc, prog1) 
insert tblproduct(productid, programid) 
values(productdef, prog2) 
insert tblproduct(productid, programid) 
values(productxyz, prog3) 

go 

... и таблица продаж по продукт

create table tblsales(productid varchar(11), salesamount numeric(18,2)) 

go 

insert tblsales(productid, salesamount) 
values(productabc, 150) 

insert tblsales(productid, salesamount) 
values(productdef, 500) 

insert tblsales(productid, salesamount) 
values(productxyz, 650) 

go 

продаж для продукта, принадлежащего prog1 предоставляется скидка в 1%:

.01 * productabcSales

или ...

+0,01 * 150 = 1,50

продаж для продукта, принадлежащего Prog2, предоставляется скидка в размере 1% (продажи минус предыдущей скидки применяемые prog1):

.01 * (. productdefSales - 01 * (productabcSales))

или ...

.01 * (500 - (.01 * 150) = 4.985

Продажи для продукта, принадлежащего prog3, получают скидку в размере 2% против суммы продаж (минус выплаченные prog2 минус (выплата по prog1)):

.02 * (.. productxyzSales - (01 * (productdefSales - (01 * productabcSales))))

или ...

.02 * (650- (. 01 * (500 - (.01 * 150))))) = 12.9003

Я думаю, что должен быть простой способ сделать это, не создавая связку временных таблиц? Может быть, CTE ?? Кроме того, в игре может быть любое количество программ ...

+0

Я создал скрипт SQL, хотя теперь я не думаю, что у меня есть время, чтобы попытаться ответить на вопрос. :) http://sqlfiddle.com/#!3/51142 –

+0

Да, CTE должен иметь возможность обрабатывать скидки рекурсивно. – HABO

+0

Как вы их определили, нет никакой реальной необходимости обрабатывать их по порядку. – RBarryYoung

ответ

1

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

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

Я использую ROW_NUMBER(), чтобы убедиться, что значения calc_order начинаются с 1 и являются непрерывными (чтобы впоследствии работал код). В order by в over() следует удалить любое случайное поведение, если в таблице calc_order есть привязки из таблицы tblprogram. Очевидно, это все, что мне нужно быть осторожными - вы знаете свои данные лучше меня, поэтому, если этот код перевернут, используйте calc_order напрямую.

select 
    ROW_NUMBER() over (order by prg.calc_order, prg.programid) as calc_order, 
    s.productid, 
    p.programid, 
    prg.discount, -- this is the additional column to hold your values 
    s.salesamount, 
    convert(decimal(7,5),0) as rebate 
into #results 
from tblsales s 
join tblproduct p on p.productid=s.productid 
join tblprogram prg on prg.programid=p.programid 

declare @calc_order int=1 

while @@ROWCOUNT>0 begin 

    update r set 
     rebate=(r.salesamount-isnull((
       select rebate 
       from #results 
       where [email protected]_order-1 
       ),0))*discount, 
     @calc_order+=1 
    from #results r 
    where [email protected]_order 

end 

select * 
from #results 

производит: -

calc_order productid programid discount salesamount rebate 
1   productabc prog1  0.01  150.00  1.50000 
2   productdef prog2  0.01  500.00  4.98500 
3   productxyz prog3  0.02  650.00  12.90030 

И только голову неизбежных вниз голосов, предложившего курсор правильный путь - если цикл while был курсор - select встроенный в update не требуется, так как вы неизбежно сохранили общую сумму скидок до сих пор - избегая работы на сервере. Я не могу понять, как избежать этого. Если вы хотите, чтобы я нажал сюда код курсора, оставьте сообщение ниже, и я добавлю его.

+1

В итоге я перешел с курсором. Пробовал все, что мог придумать, чтобы избежать этого, но, как ты сказал, - правильный инструмент в этом редком случае. Ура! – user3108433

+1

Также я не верю в чрезмерную оборону ... ВСЕГДА код по назначению! – user3108433

Смежные вопросы