假设一个包含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%的折扣:
.01*productabcSales
或者..。
.01*150 = 1.50
属于prog2的产品的销售折扣为prog1的1% (销售减去以前的折扣):
.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?而且,可以有任意数量的节目.
发布于 2013-12-16 23:04:33
这里有一个基于集合的传说,它只是试图避免这样一个事实:光标是解决这个问题的正确方法。(非常、非常、非常罕见的一次这种说法是正确的)
我向您的discount
表中添加了一个tblprogram
列--这似乎是正确的位置--但显然,我对您的用例没有真正的了解(因此您希望相应地调整我的代码)。
我使用ROW_NUMBER()
来确保calc_order
值从1开始,并且是连续的(以便代码以后工作)。如果您的order by
表中有关联,over()
中的calc_order
应该删除任何随机行为。显然,这只是我的谨慎--你比我更了解你的数据--所以如果这段代码过于防御性,直接使用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
中的select
了,因为到目前为止,您将不可避免地将回扣的总数保持在运行中--从而避免了服务器的工作。我也看不出递归cte是如何避免这种情况的。如果您想让我把游标代码扔到这里,在下面放一条消息,我会添加它。
https://stackoverflow.com/questions/20619405
复制相似问题