使用来自其他表

时间:2016-11-13 18:51:27

标签: sql sql-server sql-server-2008 loops

表1:#tdac

insert #tdac(secnum,bucketcode,acc,defqty)
select 'ax1','cor',1,'012',-100
insert #tdac(secnum,bucketcode,acc,defqty)
select 'ax1','cor',2,'012',-50

表2:#dac

insert #dac(secnum,bucketcode,acc,defqty)
select 'ax1','cor',0,'012',-125

我想通过从最早的dfqty开始从表2中减去defqty来更新表1中的caseid

If #tdac.defqty-#dac.defqty > 0, then 
    #tdac.defqty=0 and #dac.defqty = (#tdac.defqty-#dac.defqty) 
proceed to the next row. 
Continue this until the  value of (#tdac.defqty-#dac.defqty) becomes less than 0. 

在我的示例中,我想更新表1,如下所示。请帮忙

secnum  bucketcode  caseid  acc     defqty
ax1     cor         1       012     0     ((-100 -(-125)=25)>0, So make it 0)
ax1     cor         2       012    -25    ((-50 -(-25)=-25)<0, So make it -25)

3 个答案:

答案 0 :(得分:0)

我不确定我是否完全理解你的逻辑,但我认为这可以通过递归CTE完成:

我添加了另一个案例组来证明这种方法可以一次性处理不同的群体。

declare @tdac table(secnum varchar(100),bucketcode varchar(100),caseid int,acc varchar(100),defqty int);
insert @tdac(secnum,bucketcode,caseid,acc,defqty)
values('ax1','cor',1,'012',-100)
     ,('ax1','cor',2,'012',-50)
     ,('ax1','cor',3,'012',-150)
     ,('ax2','cor',1,'012',-100)
     ,('ax2','cor',2,'012',-100);

declare @dac table(secnum varchar(100),bucketcode varchar(100),caseid int,acc varchar(100),defqty int);
insert @dac(secnum,bucketcode,caseid,acc,defqty)
values('ax1','cor',0,'012',-125)
     ,('ax2','cor',0,'012',-150);

- 第一个CTE将找到所有不同的组,并将@dac的值作为起始值添加到集合

WITH DistinctGroups AS
(
    SELECT t.secnum,t.bucketcode,t.acc,d.defqty
    FROM @tdac AS t
    LEFT JOIN @dac AS d ON d.secnum=t.secnum and d.bucketcode=t.bucketcode AND d.acc=t.acc
    GROUP BY t.secnum,t.bucketcode,t.acc,d.defqty
)

- 递归CTE

,recursiveCTE AS
(
    --anchor: Get the rows with the minimal caseid from each group

    SELECT t.secnum,t.bucketcode,t.caseid,t.acc,t.defqty,CASE WHEN x.NewQty>0 THEN 0 ELSE x.NewQty END AS NewQty,CASE WHEN x.NewQty>0 THEN x.NewQty ELSE 0 END AS NewDiff
    FROM @tdac AS t
    INNER JOIN DistinctGroups AS gr ON t.secnum=gr.secnum AND t.bucketcode=gr.bucketcode AND t.acc=gr.acc
    CROSS APPLY(SELECT t.defqty-gr.defqty AS NewQty) AS x
    WHERE t.caseid=(SELECT MIN(caseid) FROM @tdac AS t2 WHERE t2.secnum=gr.secnum AND t2.bucketcode=gr.bucketcode AND t2.acc=gr.acc)

    UNION ALL

    --find the row with the next caseid and add the diff value of the previous row

    SELECT t.secnum,t.bucketcode,t.caseid,t.acc,t.defqty,CASE WHEN x.NewQty>0 THEN 0 ELSE x.NewQty END AS NewQty,CASE WHEN x.NewQty>0 THEN x.NewQty ELSE 0 END AS NewDiff
    FROM @tdac AS t
    INNER JOIN recursiveCTE AS r ON t.secnum=r.secnum AND t.bucketcode=r.bucketcode AND t.acc=r.acc
    CROSS APPLY(SELECT t.defqty+r.NewDiff AS NewQty) AS x
    WHERE t.caseid=r.caseid+1
)
select * 
from recursiveCTE
order by secnum,caseid

结果

ax1 cor 1   012 -100       0    25
ax1 cor 2   012  -50     -25     0
ax1 cor 3   012 -150    -150     0

ax2 cor 1   012 -100       0    50
ax2 cor 2   012 -100     -50     0

答案 1 :(得分:0)

UPDATE #tdac SET defqty = CASE WHEN ( (#tdac.defqty) -(F.defqty) ) > 0 THEN 0 ELSE ( (#tdac.defqty) -(F.defqty) ) END FROM #dac F WHERE F.secnum = #tdac.secnum

答案 2 :(得分:0)

为defqty构建一个运行总计(使用sum() over())。然后更新总数在校正值范围内的位置。

update tdac
set defqty = case when tdac.total >= dac.total then 0 else tdac.total - dac.total end
from 
(
  select secnum, bucketcode, acc, sum(defqty) as total
  from #dac 
  group by secnum, bucketcode, acc
) dac
join
(
  select secnum, bucketcode, acc, caseid, defqty,
    sum(defqty) over (partition by secnum, bucketcode, acc order by caseid) as total
  from #tdac
  where defqty < 0
) tdac on  tdac.secnum = dac.secnum
       and tdac.bucketcode = dac.bucketcode
       and tdac.acc = dac.acc
       and tdac.total - tdac.defqty >= dac.total;

我怀疑您想加入secnumbucketcodeacc。如果不是这种情况,请更改GROUP BYPARTITION BYON条款。

我编写了查询,以便能够处理#dac中针对同一secnumbucketcodeacc的多个条目。如果这三者是唯一的(当然是表的主键),那么您当然不需要聚合子查询,而是可以直接从#dac中选择。

以下是存储的测试:http://rextester.com/VJJY97875