日期:2014-05-18  浏览次数:20535 次

sql server 2005的表更新问题

use tempdb
go

set nocount on
go

if object_id (N'mid', N'U') is not null
  begin
  drop table mid
  create table mid
  (
  bs varchar(1) not null,
  total decimal(19, 2) not null,
  )
  end
go

if object_id (N'goal', N'U') is not null
  begin
  drop table goal
  create table goal
  (
  xh int not null,
  bs varchar(1) not null,
  num decimal(19, 2) not null,
  )
  end
go

insert mid (bs, total) values ('a', 3000)
insert mid (bs, total) values ('b', 9000)
insert mid (bs, total) values ('c', 3000)
go

insert goal (xh, bs, num) values (1, 'a', 1000)
insert goal (xh, bs, num) values (2, 'a', 1000)
insert goal (xh, bs, num) values (3, 'a', 1000)
insert goal (xh, bs, num) values (6, 'b', 3000)
insert goal (xh, bs, num) values (7, 'b', 3000)
insert goal (xh, bs, num) values (8, 'b', 3000)
insert goal (xh, bs, num) values (11, 'b', 3000)
insert goal (xh, bs, num) values (16, 'c', 2000)
insert goal (xh, bs, num) values (18, 'c', 2000)
insert goal (xh, bs, num) values (19, 'd', 500)
go

select * from mid
select * from goal

-- 前提: mid表每个bs有个总量total, goal表每个bs有对应的分量, 而且有对应的非连续递增的xh
-- 问题: goal表如何按xh递减的顺序, 用mid表的total冲减其分量(mid表的总量<=goal表分量的和)(就是用mid表的total,去抵消goal表的num, 直到把total抵消成0, 按照goal表xh递减的顺序, 从大到小抵消...)
-- 最终结果:
-- goal表的数据
-- xh bs num
-- 1 a 0 -- 3.经过1和2.a初始total=1000,原num=1000=total=1000,所以total-1000=0,num=0
-- 2 a 0 -- 2.经过1,a初始total=2000,原num=1000<total=2000,所以total-1000=1000,num=0
-- 3 a 0 -- 1.a初始total=3000,原num=1000<total=3000,所以total-1000=2000,然后num=0
-- 6 b 3000 -- 此时total=0, num=3000>total=0,所以不改
-- 7 b 0 -- 同a的说明
-- 8 b 0 -- 同a的说明
-- 11 b 0 -- 同a的说明
-- 16 c 1000 -- 原num=2000>total=1000,所以total将原来的2000冲为0即可,最终total=0,num=1000
-- 18 c 0 -- 同a
-- 19 d 500 -- mid表没有d,不改


------解决方案--------------------
SQL code




declare mycursor cursor
for
select xh,bs,num from goal order by xh desc
open mycursor
declare @xh int,@bs char(1),@num int
fetch next from mycursor into @xh,@bs,@num
while @@fetch_status=0
begin
    declare @total int,@val int
    select @total=total from mid where bs=@bs
    if @total is not null
    begin
        if @total>=@num
            set @val=@num
        else
            set @val=@total
        update goal set num=num-@val where xh=@xh
        update mid set total=total-@val where bs=@bs
    end
    fetch next from mycursor into @xh,@bs,@num
end
close mycursor
deallocate mycursor

select * from mid
select * from goal


-------------------------------

bs   total
---- ---------------------------------------
a    0.00
b    0.00
c    0.00

(3 行受影响)

xh          bs   num
----------- ---- ---------------------------------------
1           a    0.00
2           a    0.00
3           a    0.00
6           b    3000.00
7           b    0.00
8           b    0.00
11          b    0.00
16          c    1000.00
18          c    0.00
19          d    500.00

(10 行受影响)

------解决方案--------------------
SQL code

with c as
(select a.rn,a.xh,a.bs,a.num,b.total
 from 
 (select row_number() over(partition by bs order by xh desc) rn,
  xh,bs,num from goal) a
 left join mid b on a.bs=b.bs
),
d as
(select c.xh,c.bs,
case when c.total is null then c.num
when (c.total-(select isnull(sum(c2.num),0) from c c2 where c2.bs=c