2

SQL Server 2008 を使用していますが、オン状態とオフ状態の間の時間を計算するにはどうすればよいですか? 私は次の表を持っています( 順timestamp):

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

ギャップと島に対していくつかの機能を試しましたが、うまくいきませんでした。何が欠けているのかわかりません...

4

2 に答える 2

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

SQLFiddleでの実例。

于 2012-07-27T19:03:54.433 に答える
0

これが私の見解です。テーブルが「MyData」と呼ばれると仮定します。

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
于 2012-07-27T19:47:11.433 に答える