Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server:使用一条语句更新多行,并进行计算_Sql Server_Sql Server 2005_Sql Server 2008 - Fatal编程技术网

Sql server SQL Server:使用一条语句更新多行,并进行计算

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

我不知道是否可以在一个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   |  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来处理它,希望不要使用触发器或存储过程。循环记录并更新退款金额如何。如何有效地进行计算。