SQL Server:使用一个带有计算的语句更新多个行

时间:2011-05-19 07:19:41

标签: sql-server sql-server-2005 sql-server-2008

我不知道在一个SQL语句中是否可以更新退款?

我最初使用insert语句包含这三行:

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

如果退款是350,退款将更新如下,退款不能超过tranamt:

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

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

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

我认为使用一个sql语句更新refundamt是不可能的。多重声明怎么样?不希望使用商店程序。我可以使用选择更新吗?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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 :(得分: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]