SQL 从行中减去变量
有没有办法减去一个变量并将该变量的剩余部分用于 MS-SQL 中的下一列
基本上我想要做的是减去某个值并开始按顺序播放 var1-3 中的值
之前:
ID|var1|var2|var3
1| 500| 100| 200
2| 800| 400| 300
3|1200|3200|2400
示例 1 - 减去 600 我会得到
ID|var1|var2|var3
1| 0| 0| 200
2| 800| 400| 300
3|1200|3200|2400
样本 2 - 减去 750 我会得到
ID|var1|var2|var3
1| 0| 0| 50
2| 800| 400| 300
3|1200|3200|2400
样本 3 - 减去 900 我会得到
ID|var1|var2|var3
1| 0| 0| 0
2| 700| 400| 300
3|1200|3200|2400
带有“0”的字段可以为“空”。
这是我尝试过的,但非常笨重:|
DECLARE @Amount DECIMAL(18,2) = 900
CREATE TABLE #table(ID [int] NULL, var1 decimal(18,2), var2 decimal(18,2), var3 decimal(18,2))
INSERT INTO #table (ID,var1,var2,var3) VALUES (1,500,100,200)
INSERT INTO #table (ID,var1,var2,var3) VALUES (2,800,400,300)
INSERT INTO #table (ID,var1,var2,var3) VALUES (3,1200,3200,2400)
DECLARE @CurrentRow INT
DECLARE @OrgAmount DECIMAL(18,2)
WHILE (SELECT SUM( ISNULL(var1,0)) + SUM( ISNULL(var2,0)) + SUM( ISNULL(var3,0)) FROM #table) != 0 AND @Amount != 0
BEGIN
SELECT TOP 1 @CurrentRow = ID FROM #table
WHERE var1 != 0 OR var2 != 0 OR var3 != 0
ORDER BY ID ASC
UPDATE #table
SET var1 = CASE WHEN var1 - @Amount < 0 THEN 0 ELSE var1 - @Amount END,
@OrgAmount = var1
WHERE @CurrentRow = ID
SET @Amount = CASE WHEN @Amount - @OrgAmount < 0 THEN 0 ELSE @Amount - @OrgAmount END
UPDATE #table
SET var2 = CASE WHEN var2 - @Amount < 0 THEN 0 ELSE var2 - @Amount END,
@OrgAmount = var2
WHERE @CurrentRow = ID
SET @Amount = CASE WHEN @Amount - @OrgAmount < 0 THEN 0 ELSE @Amount - @OrgAmount END
UPDATE #table
SET var3 = CASE WHEN var3 - @Amount < 0 THEN 0 ELSE var3 - @Amount END,
@OrgAmount = var3
WHERE @CurrentRow = ID
SET @Amount = CASE WHEN @Amount - @OrgAmount < 0 THEN 0 ELSE @Amount - @OrgAmount END
END
SELECT * FROM #table
DROP TABLE #table
感谢您的协助。
Is there a way to subtract a variable and use the remainder of that variable for the next column in MS-SQL
Basically what i want to do is subtract a certain value and start playing of the values from var1-3 in order
Before:
ID|var1|var2|var3
1| 500| 100| 200
2| 800| 400| 300
3|1200|3200|2400
Sample 1 - Subtract 600 I would get
ID|var1|var2|var3
1| 0| 0| 200
2| 800| 400| 300
3|1200|3200|2400
Sample 2 - Subtract 750 I would get
ID|var1|var2|var3
1| 0| 0| 50
2| 800| 400| 300
3|1200|3200|2400
Sample 3 - Subtract 900 I would get
ID|var1|var2|var3
1| 0| 0| 0
2| 700| 400| 300
3|1200|3200|2400
The field with '0' can be 'null'.
This is what i have tried but is very bulky :|
DECLARE @Amount DECIMAL(18,2) = 900
CREATE TABLE #table(ID [int] NULL, var1 decimal(18,2), var2 decimal(18,2), var3 decimal(18,2))
INSERT INTO #table (ID,var1,var2,var3) VALUES (1,500,100,200)
INSERT INTO #table (ID,var1,var2,var3) VALUES (2,800,400,300)
INSERT INTO #table (ID,var1,var2,var3) VALUES (3,1200,3200,2400)
DECLARE @CurrentRow INT
DECLARE @OrgAmount DECIMAL(18,2)
WHILE (SELECT SUM( ISNULL(var1,0)) + SUM( ISNULL(var2,0)) + SUM( ISNULL(var3,0)) FROM #table) != 0 AND @Amount != 0
BEGIN
SELECT TOP 1 @CurrentRow = ID FROM #table
WHERE var1 != 0 OR var2 != 0 OR var3 != 0
ORDER BY ID ASC
UPDATE #table
SET var1 = CASE WHEN var1 - @Amount < 0 THEN 0 ELSE var1 - @Amount END,
@OrgAmount = var1
WHERE @CurrentRow = ID
SET @Amount = CASE WHEN @Amount - @OrgAmount < 0 THEN 0 ELSE @Amount - @OrgAmount END
UPDATE #table
SET var2 = CASE WHEN var2 - @Amount < 0 THEN 0 ELSE var2 - @Amount END,
@OrgAmount = var2
WHERE @CurrentRow = ID
SET @Amount = CASE WHEN @Amount - @OrgAmount < 0 THEN 0 ELSE @Amount - @OrgAmount END
UPDATE #table
SET var3 = CASE WHEN var3 - @Amount < 0 THEN 0 ELSE var3 - @Amount END,
@OrgAmount = var3
WHERE @CurrentRow = ID
SET @Amount = CASE WHEN @Amount - @OrgAmount < 0 THEN 0 ELSE @Amount - @OrgAmount END
END
SELECT * FROM #table
DROP TABLE #table
Thank you for the assist.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
虽然我同意评论,这可能可以更好地布局,但以下 sql 显示了解决该问题的一种方法:
返回
CTE_Data 只是输入数据,您可以为源表更改它。
CTE_RunningTotals 包含原始数据,以及表中直到当前行/列的所有值的运行总计。
如果前一行/列为零(即相减值大于到目前为止的运行总计),则从当前值中取出相减值,否则返回数据值。
如果您在 CTE 声明之后
select * from CTE_RunningTotals
,您可能会发现更容易弄清楚发生了什么,这样您就可以看到工作情况。While I agree with the comments, that this probably could be better laid out, the following sql shows one approach to the problem:
returns
CTE_Data is simply the input data, you can change this for your source table.
CTE_RunningTotals contains the raw data, plus a running total of all the values in the table upto the current row/column.
If the previous row/column is zero (ie the subtract value is greater than the running total so far) the subtract value is taken from the current value, otherwise the data value is returned.
You might find it easier to work out what is going on if you
select * from CTE_RunningTotals
after the CTE declarations so that you can see the working.