Sql server 将带有标志的行中的数字滚动到不带标志的下一行

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

我有点困惑于如何解决我正在研究的这个问题。我从一个更大的问题开始,但我设法将其简化为这个问题,同时保持良好的性能不变

假设我有以下结果集。AggregateMe是我从SQL条件中派生出来的东西

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、日期选择行号