考虑一个包含3个DiscountPrograms的表,其中包含已分配的计算顺序
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%的折扣:
0.01 * productabcSales
或......
.01 * 150 = 1.50
属于prog2的产品的销售额给予1%的折扣(销售额减去prog1应用的先前折扣):
0.01 *(productdefSales - (01 * productabcSales))
或......
.01 *(500 - (.01 * 150)= 4.985
属于prog3的产品的销售额给予2%的折扣,相对于salesamount减去(已经由prog2支付的金额减去(按prog1支付)):
0.02 *(productxyzSales - (01 *(productdefSales - (01 * productabcSales))))
或......
.02 *(650 - (.01 *(500 - (。01 * 150)))))= 12.9003
我在想,如果不创建一堆临时表,必须有一个简单的方法吗?也许CTE?此外,可以有任意数量的节目......
答案 0 :(得分:1)
这里是一个基于集合的kludge,它只是试图避免光标是解决这个问题的正确方法......(这个陈述是真的非常非常非常罕见的场合之一)< / p>
我在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 calc_order=@calc_order-1
),0))*discount,
@calc_order+=1
from #results r
where r.calc_order=@calc_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
会不需要,因为到目前为止你不可避免地会保留一笔累计回扣 - 避免为服务器工作。我无法看到递归cte如何避免这种情况。如果您希望我将光标代码放入此处,请在下面留言,然后我将其添加。