SQL Server: обновить несколько строк одним оператором с вычислением - PullRequest
1 голос
/ 19 мая 2011

Я не знаю, возможно ли в одном операторе SQL обновить возврат?

У меня изначально есть три строки, используя оператор вставки:

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

Если возврат 350, возврат будет обновлен следующим образом, возврат не может быть больше, чем транер:

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

При повторном возврате с 50, возврат будет обновлен следующим образомдумаю, что это невозможно обновить refundamt с помощью одного оператора SQL.Как насчет множественного насыщения?Не надеясь использовать процедуру магазина.Могу ли я использовать выбрать обновление ?

Ответы [ 3 ]

2 голосов
/ 19 мая 2011

Я думаю, что это работает.Это одно утверждение.Не самая красивая.И я думаю, что в реальной таблице транзакций есть больше столбцов (например, номер счета):

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 голосов
/ 19 мая 2011

Немного грязно, но вот что я придумал:

Код для настройки ваших базовых таблиц ...

-- 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]
0 голосов
/ 19 мая 2011

Что-то вроде ...: (нуждается в работе, но дает концептуальную идею)

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
...