我在列中有这些值: 1 1 1 -1 -1 1 1 1 1 1 -1 1
我需要一个查询,它将返回第一个连续的值之和,然后返回下一个,依此类推,每次该值与执行新总和之前的值不同。 根据这个例子,这些连续总和的结果如下:
3
-2
5
-1
1
在速度和资源使用方面,通过每个值循环并计算每个总和或者可以在一个查询中完成此操作的最佳方法是什么? 有什么想法吗?
---------- EDITION ------------
我设法使用row_number over partition添加以下列:
COL A COL B
1 1
2 1
3 1
1 -1
2 -1
1 1
2 1
3 1
....等等
这有什么帮助吗?
---------第二版--------- 我有这个:
SELECT ROW_NUMBER() OVER (PARTITION BY T.RES ORDER BY T.ID_Test_Case DESC) AS GRP,
T.RES,
T.ID_Test_Case
FROM (
SELECT TEST_CASE.ID_Test_Case,
(CASE WHEN TEST_RESULT.Name = TR2.Name THEN 1 ELSE -1 END) AS RES
FROM (Join from all tables needed)
WHERE (All Conditions) ) T
ORDER BY T.ID_Test_Case DESC
)
这是我正在检索值1和-1的地方,由于order by子句,它总是被排序相同。我只能使用Test_Case.ID来订购并且是一个独特的领域...希望这有帮助
答案 0 :(得分:3)
使用递归CTE:
DECLARE @tmp TABLE
(
RowID int IDENTITY(1,1),
Value int
)
INSERT INTO @tmp
VALUES (1),(1),(1),(-1),(-1),(1),(1),(1),(1),(1),(-1),(1)
;WITH
Groups AS
(
SELECT RowID As GroupID,
RowID As RowID,
Value As Value
FROM @tmp
WHERE RowID = 1
UNION ALL
SELECT CASE
WHEN this.Value = prev.Value THEN prev.GroupID
ELSE this.RowID
END As GroupID,
this.RowID As RowId,
this.Value AS Value
FROM @tmp this
INNER JOIN Groups prev ON this.RowID = prev.RowID + 1
)
SELECT SUM(Value)
FROM Groups
GROUP BY GroupID
<强>解释强>
您想要的是将行分成顺序相等的值组。这里的RowID
用作行号。
CTE以RowID = 1
开头,创建了一个新的&#34;组&#34;
UNION ALL
递归地添加RowID = 2, 3, 4
等。每次迭代时,它会考虑其值是否等于前一行的值。如果是,则使用与前一行相同的GroupID
。如果没有,则使用其RowID
启动新组。
我们现在只需要总结每组的价值即可得到你想要的东西。
要查看此工作的内部结构,请将最终SELECT
替换为SELECT * FROM Groups
答案 1 :(得分:2)
应该是不言自明的。不优雅,但会完成工作。
Create Table _Numbercolumn (val int)
Create Table _RandValues ( random int)
Create Table _Sum([sum] int)
insert into _RandValues values(1)
insert into _RandValues values(-1)
while ( select COUNT(val) from _Numbercolumn ) < 100
BEGIN
Insert into _numbercolumn select top 1 random from _RandValues order by NEWID()
END
DECLARE Number_Cursor CURSOR FOR SELECT val from _Numbercolumn
DECLARE @CurrentSum int, @CursorVal int
OPEN Number_Cursor;
Set @CurrentSum = 0
FETCH NEXT FROM Number_Cursor into @CursorVal;
WHILE @@FETCH_STATUS = 0
BEGIN
IF SIGN(@CurrentSum) <> SIGN(@CursorVal)
BEGIN
INSERT INTO _Sum Values(@CurrentSum)
SET @CurrentSum = @CursorVal
END
ELSE
SET @CurrentSum = @CurrentSum + @CursorVal
FETCH NEXT FROM Number_Cursor into @CursorVal;
END;
CLOSE Number_Cursor;
DEALLOCATE Number_Cursor;
GO
Select * from _Sum
答案 2 :(得分:1)
以下是与您的设置相同的唯一排序:
SELECT *
INTO #t
FROM (VALUES (1,1),(2,1),(3,1),(4,-1),(5,-1),(6,1),(7,1),(8,1),(9,1),(10,1),(11,-1),(12,1)) AS t(RowNbr, VALUE);
现在,使用上面的内容,您可以在一个查询中完成(可能有更好的方法,但这应该足够了):
;WITH ChangingRows AS (
SELECT t1.RowNbr, t1.Value, ROW_NUMBER() OVER (ORDER BY t1.RowNbr) AS Ord
FROM #t t1
LEFT JOIN #t t2 ON t1.RowNbr = t2.RowNbr - 1
WHERE t1.Value != ISNULL(t2.Value, 0)
)
SELECT (c1.RowNbr - ISNULL(c2.RowNbr, 0)) * c1.Value as Total
FROM ChangingRows c1
LEFT JOIN ChangingRows c2 ON c2.Ord = c1.Ord - 1;