2011-05-19 74 views
1

我不知道这是否可能在一条SQL语句中更新refundamt?SQL Server:用一条语句更新多行并进行计算

我有这三行最初,使用插入语句:

NO | TRANAMT | REFUNDAMT 
1 | 100  | 0 
2 | 200  | 0 
3 | 300  | 0 

如果退款是350,refundamt将被更新为跟进,refundamt不能更然后tranamt:

NO | TRANAMT | REFUNDAMT 
1 | 100  | 100 
2 | 200  | 200 
3 | 300  | 50 

用50再次退款时,refundamt将更新如下

NO | TRANAMT | REFUNDAMT 
1 | 100  | 100 
2 | 200  | 200 
3 | 300  | 100 

我瘦k这是不可能使用一个sql语句更新refundamt。如何多重处理?不希望使用商店程序。我可以使用选择更新

+1

不太清楚 - 你能更好地解释如何** **你从第一状态得到第二,然后到第三??你的意思是*如果退款是350 * - **什么**退款?什么专栏?我在第一种状态下根本看不到任何退款......并且您如何从第二种状态获得第三种状态? 50你的退款是什么意思?为什么它只应用于第三行?规则是什么** ?? – 2011-05-19 07:24:21

+1

当你说“一个”陈述时 - 你在问什么。这将是一个简单的存储过程,其中声明的变量用于跟踪退款金额和一个逐行应用的while循环,直到退款全部用完。但是这符合你对单一陈述的期望吗?对我而言,任何以单一“批次”运行的东西都是一种陈述。 – RThomas 2011-05-19 07:27:29

+0

您的退款金额是否分摊到每笔交易中。通过这个我的意思是它需要350然后开始在TRANAMT No1,起飞100,然后移动到No2,需要200,然后移动到No3采取过去50. – kevchadders 2011-05-19 07:46:05

回答

0

喜欢的东西...:(需要工作,但给出了一个概念性的想法)

Declare @pRefund Money 
SET @pRefund = 350 

WHILE @pRefund > 0 
BEGIN 
    /** SELECT Transaction Amount of min primary key where recorded refundamt is less than tranamt 
    Apply matching refund 
    Reduce @pRefund by amount applied 
    If @pRefund is now less then next highest TransAMT Then apply whats left otherwise loop again 
    refund has now been all applied and loop will exit */ 
END 
2

我想这样的作品。这是一个单一的声明。不是最漂亮的。和我想像真正的交易表具有更多的列(如一个帐号):

declare @RefundAmt int 
set @RefundAmt = 350 

; with Refunds as (
    select 
     top 1 
     NO, 
     TRANAMT, 
     CASE WHEN TRANAMT-REFUNDAMT < @RefundAmt THEN TRANAMT ELSE REFUNDAMT + @RefundAmt END as REFUNDAMT, 
     CASE WHEN TRANAMT-REFUNDAMT < @RefundAmt THEN @RefundAmt - (TRANAMT-REFUNDAMT) ELSE 0 END as Remaining 
    from 
     dbo.Transactions 
    where REFUNDAMT < TRANAMT ORDER BY NO 
    union all 
    select 
     t2.NO, 
     t2.TRANAMT, 
     CASE WHEN t2.TRANAMT-t2.REFUNDAMT < t1.Remaining THEN t2.TRANAMT ELSE t2.REFUNDAMT + t1.Remaining END as REFUNDAMT, 
     CASE WHEN t2.TRANAMT-t2.REFUNDAMT < t1.Remaining THEN t1.Remaining - (t2.TRANAMT-t2.REFUNDAMT) ELSE 0 END as Remaining 
    from 
     Refunds t1 
      inner join 
     dbo.Transactions t2 
      on 
       t1.NO = t2.NO - 1 and 
       t1.Remaining > 0 
) 
update t set REFUNDAMT = r.REFUNDAMT 
from 
    dbo.Transactions t 
     inner join 
    Refunds r 
     on 
      t.NO = r.NO 
0

有点凌乱,但这里是我想出了:

代码来设置你的基本表.. 。

-- setup code 
CREATE TABLE #tmp (
    [NO] int identity(1,1), 
    [TRAN] money, 
    [REFUND] money 
) 
INSERT #tmp VALUES (100, 0) 
INSERT #tmp VALUES (200, 0) 
INSERT #tmp VALUES (300, 0) 

代码添加到您的退款金额...

DECLARE @amt money SET @amt = 50 
UPDATE u 
SET REFUND = 
    CASE WHEN u.[REFUND] = u.[TRAN] THEN u.[REFUND] --'already full - do nothing' 
     WHEN cumulativepretran >= aiming_for_ref THEN u.[REFUND] --'after all - do nothing' 
     WHEN cumulativetran + cumulativeref > ((totalref + @amt) - u.[TRAN]) THEN (totalref + @amt + u.[REFUND]) - (cumulativeref) --'calc' 
     ELSE u.[TRAN] END -- 'fill-er-up' 
FROM #tmp u 
INNER JOIN (SELECT *, 
    ISNULL((select sum([REFUND]) FROM #tmp WHERE [NO] <= t.[NO]), 0) 'cumulativeref', 
    ISNULL((select sum([TRAN]) FROM #tmp WHERE [NO] <= t.[NO]), 0) 'cumulativetran', 
    ISNULL((select sum([REFUND]) FROM #tmp WHERE [NO] < t.[NO]), 0) 'cumulativepreref', 
    ISNULL((select sum([TRAN]) FROM #tmp WHERE [NO] < t.[NO]), 0) 'cumulativepretran', 
    ISNULL((select sum([REFUND]) FROM #tmp), 0) 'totalref', 
    ISNULL((select sum([REFUND]) FROM #tmp), 0) + @amt 'aiming_for_ref' 
FROM #tmp t) as m ON m.[NO] = u.[NO]