2016-11-13 71 views
3

表1動態值的循環:#tdac更新SQL表在從其他表

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 

我想通過從表中減去defqty更新表1 dfqty 2從最早的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) 
+0

問題解決了嗎?你需要進一步的幫助嗎?請允許我提示一個提示:如果這個問題已經解決,那麼在(最佳)答案的投票櫃檯下面勾選驗收檢查將會非常友善。這將1)標記這個問題已解決2)使追隨者更容易找到最佳的解決方案3)支付點給回答者和4)支付點給你。一旦你自己超過了15分的邊界,你又被要求對貢獻進行投票。這是SO的方式來說聲謝謝。快樂編碼! – Shnugo

回答

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 
) 

-the遞歸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 
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 
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 BY,PARTITION BYON條款。

我寫了查詢,以便能夠處理#dac中的幾個條目,它們分別是secnum,bucketcodeacc。如果三者是唯一的(表中的主鍵然後假設),當然你不需要聚合子查詢,而是可以直接從#dac中選擇。

這裏是存儲的測試:http://rextester.com/VJJY97875

+0

我沒有建議'SUM()OVER()',因爲我認爲這在SQL Server 2008中不受支持。但文檔實際上並沒有提到這個限制。你確定,這在這裏有效嗎?目前還沒有機會進行測試...... – Shnugo

+0

@Shnugo:我無法測試。我查閱了文檔,他們說'sum()over()'在SQL Server 2008中可用,所以我使用了這個。看起來他們僅在2012年添加了缺少窗口功能(行/範圍子句)。 –

+0

搜索了一下,發現[this](http://stackoverflow.com/q/19684249/5089204)。 Martin Smith在下面的評論中指出,「OVER(PARTITION BY ... ORDER BY)」是在2012年推出的...... OP將不得不嘗試:-) – Shnugo