Sql server 有没有一种方法可以使用窗口函数来保持最小总数为0,而不必使用循环?
我试图避免使用循环来获得运行总数。这是一个简化版本;真实版本包括几个类别的小计。我知道我可以使用窗口函数[@Xata2]来实现这一点,但如果将总数限制为非负(即,如果总数为负,则使用0)[@Xata3],我想不出一种非循环方式来实现这一点,因为我设置的任何条件都在当前行上,而不是累计总数Sql server 有没有一种方法可以使用窗口函数来保持最小总数为0,而不必使用循环?,sql-server,tsql,window-functions,Sql Server,Tsql,Window Functions,我试图避免使用循环来获得运行总数。这是一个简化版本;真实版本包括几个类别的小计。我知道我可以使用窗口函数[@Xata2]来实现这一点,但如果将总数限制为非负(即,如果总数为负,则使用0)[@Xata3],我想不出一种非循环方式来实现这一点,因为我设置的任何条件都在当前行上,而不是累计总数 DECLARE @Xata TABLE ( ID INTEGER IDENTITY , result INTEGER
DECLARE @Xata TABLE (
ID INTEGER IDENTITY
, result INTEGER
)
DECLARE @Xata2 TABLE (
ID INTEGER IDENTITY
, result INTEGER
, total INTEGER
)
DECLARE @Xata3 TABLE (
ID INTEGER IDENTITY
, result INTEGER
, total INTEGER
)
DECLARE @result INTEGER
, @total INTEGER
, @Counter INTEGER
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
-- @Xata2: WINDOWING FUNCTION
INSERT INTO @Xata2
SELECT result
, SUM(result) OVER (ORDER BY ID)
FROM @Xata
SELECT ID
, result
, total AS total_x2_neg
FROM @Xata2
SET @Counter = 0
WHILE @Counter < (SELECT MAX(ID) FROM @Xata)
BEGIN
SET @Counter += 1
SELECT @result = result FROM @Xata WHERE ID = @Counter
SET @total = ISNULL((SELECT total FROM @Xata3 WHERE ID = @Counter - 1), 0)
INSERT INTO @Xata3
SELECT @result
, IIF(@result + @total < 0, 0, @result + @total)
END
SELECT ID
, result
, total AS total_x3_noneg
FROM @Xata3
DECLARE@Xata表(
ID整数标识
,结果整数
)
声明@Xata2表(
ID整数标识
,结果整数
,总整数
)
声明@Xata3表(
ID整数标识
,结果整数
,总整数
)
声明@result整数
,@总整数
,@计数器整数
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
--@Xata2:窗口功能
插入@Xata2
选择结果
,总和(结果)超过(按ID排序)
来自@Xata
选择ID
,结果
,总计为总计×2×负
来自@Xata2
设置@Counter=0
当@Counter<(从@Xata中选择最大值(ID)
开始
设置@Counter+=1
从@Xata中选择@result=result,其中ID=@Counter
设置@total=ISNULL((从@Xata3中选择total,其中ID=@Counter-1),0)
插入@Xata3
选择@result
,IIF(@result+@total<0,0,@result+@total)
结束
选择ID
,结果
,总计为总计×3
来自@Xata3
编辑
我把整件事都写进了另一个连续的总数里
什么时候
顺便说一句,我希望每个人都像这样工作
DECLARE @Xata TABLE (
ID INTEGER IDENTITY
, result INTEGER
)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
INSERT INTO @Xata (result) SELECT ROUND(RAND()* 9 - 4.5, 0)
SELECT x.ID, x.result, x.RT1, SUM(IIF(x.RT1<0,0,x.RT1)) OVER (ORDER BY ID) as RT2
from (
SELECT ID, result
, SUM(result) OVER (ORDER BY ID) as RT1
FROM @Xata
) as x
ORDER BY x.ID
DECLARE@Xata表(
ID整数标识
,结果整数
)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
插入@Xata(结果)选择圆形(RAND()*9-4.5,0)
选择x.ID,x.result,x.RT1,SUM(IIF)(x.RT1我的第一次尝试没有正确返回,谢谢@Menno的提示
使用递归CTE尝试这种方法
结果
ID rt runningTotalNoNeg
1 -3 0
2 1 1
3 2 3
4 2 5
5 0 5
6 0 5
7 -4 1
8 -3 0
9 2 2
10 3 5
尝试将sum
窗口函数与case
语句一起使用:
select id, result,
case when [sum] < 0 then 0 else [sum]
from (
select id,
result,
sum(result) over (order by id) [sum]
from MyTable
) a
选择id、结果、,
当[sum]<0时,则为0,否则为[sum]
从(
选择id,
结果,,
总和(结果)超过(按id排序)[总和]
从MyTable
)a
您能解释一下您的查询背后的逻辑以及它应该做什么吗?这是我很久以来看到的最好的复制。Upvote@Nick.McDermaid我也很欣赏重新编程,但我更喜欢固定值,而不是固定值输出。在这里使用随机值会使您更难看到解决方案是否正确返回…一个是的,我这边有+1。@DaveX让我们假设第7行包含一个结果-6
。应该total\ux3\uNoneg
导致0
或5
?@Menno,我想第7到8行回答了你的问题。我们有一个1,一个结果-3
,在那里我们看到一个0
。我认为这是:计算减法,但永远不会低于零。这不会导致第2行的值1
,对吗?样本数据是随机的,因此第2行总是不同的。但对于1
的输入值(在字段r1
中),是的,它返回1
。你为什么不自己运行代码?嗯,等一下-你现在是我重新检查的时候了,你是对的,它不返回OP是什么after@Nick.McDermaid不,您编辑的版本未按预期返回。您可以尝试使用我的答案中的模型,以使用与问题中使用的值相同的值…复杂性与t有关他在示例第7行中给出了数据。@DaveX所追求的逻辑是,运行总数可能不会低于0。+1我也没有看到使用窗口函数的有效方法,递归CTE可能是最优雅的解决方案。这正是我必须更改它之前的方法。OP希望使用负值,但不低于零。因此,它是仅仅对正值求和是不够的…在给定的示例中,-4
用于从5
到1
。如果5
是4或更少,它应该降到0
…抱歉,但您的编辑无法修复此问题。您可以使用我的答案的模型尝试此操作…这还不足以让ne大吃一惊负和值。。。
select id, result,
case when [sum] < 0 then 0 else [sum]
from (
select id,
result,
sum(result) over (order by id) [sum]
from MyTable
) a