I'm使用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
我已经尝试了一些功能差距和群岛,但没有工作,我不知道我错过了什么?
以下是一张就可以了。 假设你的表被称为“迈德特”:
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
这种方法首先过滤掉重复,反复断行。 只有状态开关离开了,“结束时间”可以通过搜索基础上的下一行进行检索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
在SQL小提琴活生生的例子。