2013-09-25 19 views
0

對於如何解決我正在處理的這個特定問題,我感到有些沮喪。我從一個更大的問題開始,但我設法將其簡化成這個,同時保持良好的性能。將帶有標誌的行從一行中滾動到沒有標誌的下一行

說我有以下結果集。 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(真),或者,如果你喜歡,如果是真的,我想計數彙集到下一行,其中AggregateMe(或條件)不計算爲true。 聚合函數或子查詢與PARTITION BY一樣是公平的遊戲。

例如,上面的結果集將變成:

MinutesElapsed  ID Type 
2680    1 A  
1300    1 B  
1550    1 C  
1425    1 A  
10100    2 A  

有沒有乾淨的方式做到這一點?如果你願意,我可以分享更多關於原始問題的知識,但這有點複雜。

編輯添加:單獨SUM和GROUP BY將無法正常工作,因爲一些款項將滾動到錯誤的行中。我的示例數據沒有反映這種情況,所以我在這種情況可能發生的地方添加了行。在更新後的示例數據中,以最簡單的方式使用聚合函數會導致將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) 
+1

用於確定哪一行是「下一個」行的順序是什麼? – RBarryYoung

+0

我們需要一個列來指示您的行的順序,否則我們不會知道下一行是哪一行 – Lamak

+0

添加的行號。我實際上已經在使用行號作爲此問題的一部分。在我的情況下,我使用了select ROW_NUMBER()(按ID,Date排序) – John

回答

1

這裏查詢您需要執行, 這是不乾淨的,也許你會優化它:

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 
    ) 
); 

測試here

希望它有助於你的問題。 隨時提問。

0

通過看你的結果集看起來像下面將工作,

SELECT ID,Type,SUM(MinutesElapsed) 
FROM mytable 
GROUP BY ID,Type 

但是,如果沒有尋找到原始數據集不能告訴是肯定的。