2012-07-27 56 views
2

我正在使用SQL Server 2008,如何計算開啓和關閉狀態之間的時間?我有以下表(由timestamp訂購):計算開啓和關閉狀態行之間的時間SQL Server

ID | EQUIP_ID | TIMESTAMP   | STATUS (1 on/0 off) 
1 |  1 | 21/05/2012 13:00:00 | 1 
3 |  1 | 21/05/2012 13:04:00 | 1 
4 |  1 | 21/05/2012 13:05:00 | 0 
6 |  1 | 21/05/2012 13:09:00 | 1 
7 |  1 | 21/05/2012 13:10:00 | 1 
9 |  1 | 21/05/2012 13:12:00 | 1 
10 |  1 | 21/05/2012 13:13:00 | 0 
10 |  1 | 21/05/2012 13:14:00 | 1 
10 |  1 | 21/05/2012 13:15:00 | 0 

我期待這樣的結果:

EQUIP_ID | START    |   END   | STATUS 
    1 | 21/05/2012 13:00:00 | 21/05/2012 13:05:00 | 1  (WORKING) 
    1 | 21/05/2012 13:05:00 | 21/05/2012 13:09:00 | 0  (STOPPED) 
    1 | 21/05/2012 13:09:00 | 21/05/2012 13:13:00 | 1 
    1 | 21/05/2012 13:13:00 | 21/05/2012 13:14:00 | 0 
    1 | 21/05/2012 13:14:00 | 21/05/2012 13:15:00 | 1 

我已經試過了差距和島嶼的一些功能,但沒有工作,我不知道我失蹤了什麼...

+0

也許這個例子可以讓你開始:http://stackoverflow.com/questions/4738587/select-rows-where-price-didnt-change – 2012-07-27 18:57:31

+0

使用這個例子i'm不能得到正確的間隔前:第一工作行將返回結束時間13:04不是13:05 ... – wesley 2012-07-27 19:03:30

回答

0

以下是一張就可以了。假設你的表被稱爲「邁德特」:

WITH operating AS 
(
    SELECT 
     d.EQUIP_ID 
     , d.[TIMESTAMP] 
     , d.[STATUS] 
     , ROW_NUMBER() OVER (PARTITION BY EQUIP_ID ORDER BY [TIMESTAMP]) RowNum 
     , ROW_NUMBER() OVER (PARTITION BY EQUIP_ID ORDER BY [TIMESTAMP]) - 
      ROW_NUMBER() OVER (PARTITION BY EQUIP_ID, [STATUS] ORDER BY [TIMESTAMP]) AS [Group] 
    FROM 
     MyData d 
) 
SELECT 
    state1.EQUIP_ID 
    , MIN(state1.[TIMESTAMP]) [START] 
    , MAX(state2.[TIMESTAMP]) [END] 
    , state1.STATUS 
FROM 
    operating state1 
LEFT JOIN 
    operating state2 
    ON 
    state1.RowNum = state2.RowNum - 1 
WHERE 
    state2.[TIMESTAMP] IS NOT NULL 
GROUP BY 
    state1.EQUIP_ID, state1.[STATUS], state1.[Group] 
ORDER BY 
    MIN(state1.[TIMESTAMP]) 

它利用ROW_NUMBER()功能的確定狀態的每個EQUIP_ID變化。然後它只是發現狀態何時開始(MIN([TIMESTAMP])),然後我將它與下一行中的結束時間(MAX([TIMESTAMP]))進行匹配(請參閱RowNum上的自加入)。 WHERE消除了沒有結束時間的最後一行。我得到的結果是:

EQUIP_ID | START     | END      | STATUS 
---------+-------------------------+-------------------------+------- 
     1 | 2012-05-21 13:00:00.000 | 2012-05-21 13:05:00.000 |  1 
     1 | 2012-05-21 13:05:00.000 | 2012-05-21 13:09:00.000 |  0 
     1 | 2012-05-21 13:09:00.000 | 2012-05-21 13:13:00.000 |  1 
     1 | 2012-05-21 13:13:00.000 | 2012-05-21 13:14:00.000 |  0 
     1 | 2012-05-21 13:14:00.000 | 2012-05-21 13:15:00.000 |  1 
+0

只是工作!非常快! TNKS – wesley 2012-07-27 20:02:14

2

這種方法首先過濾出重複的和重複關閉的行。只剩下狀態開關,可以通過搜索基於row_number的下一行來檢索「結束時間」。

; with numbered as 
     (
     select row_number() over (partition by equip_id order by timestamp) rn 
     ,  * 
     from YourTable 
     ) 
,  nodups as 
     (
     select row_number() over (partition by cur.equip_id order by cur.timestamp) rn 
     ,  cur.equip_id 
     ,  cur.timestamp 
     ,  cur.status 
     from numbered cur 
     left join  
       numbered prev 
     on  cur.rn = prev.rn + 1 
       and cur.status = prev.status 
     where prev.id is null 
     ) 
select cur.rn 
,  cur.equip_id 
,  cur.timestamp as StartTime 
,  next.timestamp as EndTime 
,  cur.status 
from nodups cur 
left join  
     nodups next 
on  next.rn = cur.rn + 1 
     and next.equip_id = cur.equip_id 

Live example at SQL Fiddle.

相關問題