Sql server SQL Server:使用一条语句更新多行,并进行计算
我不知道是否可以在一个SQL语句中更新退款金额 使用insert语句,我最初有这三行:Sql server SQL Server:使用一条语句更新多行,并进行计算,sql-server,sql-server-2005,sql-server-2008,Sql Server,Sql Server 2005,Sql Server 2008,我不知道是否可以在一个SQL语句中更新退款金额 使用insert语句,我最初有这三行: NO | TRANAMT | REFUNDAMT 1 | 100 | 0 2 | 200 | 0 3 | 300 | 0 如果退款为350,退款金额将更新如下,退款金额不能大于交易金额: NO | TRANAMT | REFUNDAMT 1 | 100 | 100 2 | 200 | 200 3
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退款时,退款金额将更新如下
NO | TRANAMT | REFUNDAMT
1 | 100 | 100
2 | 200 | 200
3 | 300 | 100
我认为这是不可能用一条sql语句更新的。多重状态如何?不希望使用存储过程。我可以使用select update吗?类似于…:的东西需要工作,但给出了一个概念性的想法
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
我认为这是可行的。这是一个单一的声明。不是最漂亮的。我认为real Transactions表有更多的列,例如帐号:
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
有点乱,但我想到的是: 设置基表的代码
-- 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]
不清楚-你能更好地解释一下你是如何从第一个状态到第二个状态再到第三个状态的吗??如果退款是350,你的意思是什么?什么退款?什么栏目??在第一个州,我看不到任何退款。。。。你如何从第二个州进入第三个州??50英镑的退款是什么意思?为什么只适用于第三排??规则是什么?当你说一句话时,你在问什么。这将是一个简单的存储过程,它有一个声明的变量来跟踪退款金额,还有一个while循环来逐行应用,直到退款用完为止。但是,这是否满足了你对单一声明的期望?对我来说,在一个批次中运行的任何东西都是一份声明。您的退款金额是否分布在每笔交易中。我的意思是,它需要350,然后从变速器1号开始,起飞100,然后移动到2号,采取200,然后移动到3号,采取最后50。触发器是解决你的问题,你可以使用触发器。当退款金额为350时,触发器将根据更新退款金额的条件触发,当退款金额为50时,触发器将再次触发。您可以使用触发器中的if和else来处理它,希望不要使用触发器或存储过程。循环记录并更新退款金额如何。如何有效地进行计算。