Sql server 将带有标志的行中的数字滚动到不带标志的下一行
我有点困惑于如何解决我正在研究的这个问题。我从一个更大的问题开始,但我设法将其简化为这个问题,同时保持良好的性能不变 假设我有以下结果集。AggregateMe是我从SQL条件中派生出来的东西Sql server 将带有标志的行中的数字滚动到不带标志的下一行,sql-server,subquery,aggregate-functions,Sql Server,Subquery,Aggregate Functions,我有点困惑于如何解决我正在研究的这个问题。我从一个更大的问题开始,但我设法将其简化为这个问题,同时保持良好的性能不变 假设我有以下结果集。AggregateMe是我从SQL条件中派生出来的东西 MinutesElapsed AggregateMe ID Type RowNumber 1480 1 1 A 1 1200 0 1 A 2 1300
MinutesElapsed AggregateMe ID Type RowNumber
1480 1 1 A 1
1200 0 1 A 2
1300 0 1 B 3
1550 0 1 C 4
725 1 1 A 5
700 0 1 A 6
1900 1 2 A 7
3300 1 2 A 8
4900 0 2 A 9
如果AggregateMe为1 true,或者如果您愿意,如果为true,我希望将计数聚合到AggregateMe或条件计算结果不为true的下一行。
聚合函数或子查询是公平的游戏,就像分区一样
例如,上述结果集将变为:
MinutesElapsed ID Type
2680 1 A
1300 1 B
1550 1 C
1425 1 A
10100 2 A
有没有干净的方法可以做到这一点?如果你愿意,我可以分享更多关于原始问题的信息,但它有点复杂
编辑为添加:单独使用SUM和GROUP BY将不起作用,因为某些SUM将滚动到错误的行中。我的示例数据没有反映这种情况,所以我在可能发生这种情况的地方添加了行。在更新后的示例数据中,以最简单的方式使用聚合函数将导致2680计数和1425计数一起滚动,这是我不希望看到的
编辑:如果你想知道我是怎么来到这里的,给你。我将汇总关于程序在某个ActionType中保留了多长时间的统计信息,我的第一步是创建这个子查询。请随意批评:
select
ROW_NUMBER() over(order by claimid, insertdate asc) as RowNbr,
DateDiff(mi, ahCurrent.InsertDate, CASE WHEN ahNext.NextInsertDate is null THEN GetDate() ELSE ahNext.NextInsertDate END) as MinutesInActionType,
ahCurrent.InsertDate, ahNext.NextInsertDate,
ahCurrent.ClaimID, ahCurrent.ActionTypeID,
case when ahCurrent.ActionTypeID = ahNext.NextActionTypeID and ahCurrent.ClaimID = ahNext.NextClaimID then 1 else 0 end as aggregateme
FROM
(
select ROW_NUMBER () over(order by claimid, insertdate asc) as RowNum, ClaimID, InsertDate, ActionTypeID
From autostatushistory
--Where AHCurrent is not AHPast
) ahCurrent
LEFT JOIN
(
select ROW_NUMBER() over(order by claimid, insertdate asc) as RowNum, ClaimID as NextClaimID, InsertDate as NextInsertDate, ActionTypeID as NextActionTypeID
FROM autostatushistory
) ahNext
ON (ahCurrent.ClaimID = ahNext.NextClaimID AND ahCurrent.RowNum = ahNext.RowNum - 1 and ahCurrent.ActionTypeID = ahNext.NextActionTypeID)
通过查看您的结果集,似乎以下方法可行:
SELECT ID,Type,SUM(MinutesElapsed)
FROM mytable
GROUP BY ID,Type
但如果不查看原始数据集,就无法确定答案。这里是您需要执行的查询, 它不干净,也许你会优化它:
WITH cte AS( /* Create a table containing row number */
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS ROW,
MinutesElapsed,
AggregateMe,
ID,
TYPE
FROM rolling
)
SELECT MinutesElapsed + (CASE /* adding minutes from next valid records*/
WHEN cte.AggregateMe <> 1 /*if current record is 0 then */
THEN 0 /*skip it*/
ELSE
(SELECT SUM(MinutesElapsed) /* calculating sum of all -> */
FROM cte localTbl
WHERE
cte.ROW < localTbl.ROW /* next records -> */
AND
localTbl.ROW <= ( /* until we find aggregate = 0 */
SELECT MIN(ROW)
FROM cte sTbl
WHERE sTbl.AggregateMe = 0
AND
sTbl.ROW > cte.ROW
)
AND
(localTbl.AggregateMe = 0 OR /* just to be sure :) */
localTbl.AggregateMe = 1))
END) as MinutesElapsed,
AggregateMe,
ID,
TYPE
FROM cte
WHERE cte.ROW = 1 OR NOT( /* not showing records used that are used in sum, skipping 1 record*/
( /* records with agregate 0 after record with aggregate 1 */
cte.AggregateMe = 0
AND
(
SELECT AggregateMe
FROM cte tblLocal
WHERE cte.ROW = (tblLocal.ROW + 1)
)>0
)
OR
( /* record with aggregate 1 after record with aggregate 1 */
cte.AggregateMe = 1
AND
(
SELECT AggregateMe
FROM cte tblLocal
WHERE cte.ROW = (tblLocal.ROW + 1)
)= 1
)
);
试验
希望对你的问题有所帮助。
请随意提问。确定哪一行是下一行的顺序是什么?我们需要一列指示您的行的顺序,否则我们将不知道添加的下一行是哪一行。实际上,我已经在使用行号作为这个问题的一部分。在我的例子中,我使用了按ID、日期选择行号