我有一个表格,其中包含有关移动设备上用户的状态更新;每次更新状态或更新其位置时,都会创建一个新行:
view_id time_stamp user issue_event original_value new_value
-----------------------------------------------------------------------------------------
6040462 2017-03-20 02:00:43 DerekRoberts Position updated NULL NULL
6040461 2017-03-20 02:04:01 JamesMorrison state changed Active Paused
6040461 2017-03-20 02:08:33 JamesMorrison Position updated NULL NULL
6040462 2017-03-20 02:20:42 DerekRoberts Position updated NULL NULL
6040462 2017-03-20 02:32:29 DerekRoberts state changed Active Paused
6040461 2017-03-20 02:34:11 JamesMorrison state changed Paused Active
6040461 2017-03-20 02:36:22 JamesMorrison Position updated NULL NULL
6040462 2017-03-20 02:52:47 DerekRoberts Position updated NULL NULL
6040462 2017-03-20 03:01:03 DerekRoberts state changed Paused Active
我要做的是找出每个用户保持在“暂停”状态的时间长度......这是[Paused]值与[Active]值之间的时间差[ new_value]列。为每个用户。
我以为我可以使用LEAD()为每个用户找到下一行,但是标记暂停时间结束的“活动”很少是下一行...它可能是任何数量的行进一步向下桌子。
到目前为止,我的查询如下:
;WITH UserPauseActivity AS
(SELECT [new_value],
ShiftDate = CAST([time_stamp] as DATE),
PauseStartUser = [user],
PauseEndUser = LEAD([user], 1) OVER(ORDER BY [user], [time_stamp]),
PauseStart = [time_stamp],
PauseEnd = LEAD([time_stamp], 1) OVER(ORDER BY [user], [time_stamp]),
PauseStartDate = CAST([time_stamp] AS DATE),
PauseEndDate = CAST(LEAD([time_stamp], 1) OVER(ORDER BY [user], [time_stamp]) AS DATE)
FROM [SAFE].[dbo].[cc_shift_log_view])
SELECT PauseStartUser [user],
ShiftDate,
PauseStart,
PauseEnd,
DATEDIFF(minute, PauseStart, PauseEnd) IdleTime
FROM UserPauseActivity
WHERE [new_value] = 'Paused'
AND PauseEnd IS NOT NULL
AND PauseStartUser = PauseEndUser
AND PauseStartDate = PauseEndDate
AND PauseStartDate >= '2017-03-20 00:00:00' and PauseStartDate <= '2017-03-21 23:59:59'
ORDER BY ShiftDate, [user]
返回此内容:
user ShiftDate PauseStart PauseEnd IdleTime
---------------------------------------------------------------------------------
JamesMorrison 2017-03-20 2017-03-20 02:04:01 2017-03-20 02:08:33 4
DerekRoberts 2017-03-20 2017-03-20 02:32:29 2017-03-20 02:52:47 20
PauseStart值是正确的,但是PauseEnd不正确,是表中该用户的下一行,而不是包含相应“Active”值的下一行,该值表示其暂停持续时间的实际结束,所以任何帮助解决这个问题都会非常感激!
我正在使用MS SQL Server 2012。
答案 0 :(得分:1)
假设唯一可能的状态变化来自Active - &gt;暂停 - &gt;有效......,您可以使用lead
来获得所需的结果。
select usr,shiftDate,pause_start,pause_end,datediff(second,pause_start,pause_end)/60.0 as idleTime
from (select usr,cast(time_stamp as date) as shiftDate,time_stamp as pause_start
,lead(time_stamp) over(partition by usr order by time_stamp) as pause_end
,original_value,new_value
from t
where issue_event='state changed'
) t
where original_value='Active' and new_value='Paused'
答案 1 :(得分:0)
您可以使用pivot并获得此结果,假设您只有一个从活动状态更改为暂停并暂停为活动状态,如下所示:
select view_id, [user], [1] as [PauseStart], [2] as [PauseEnd], IdleTime = Datediff(MINUTE, [1],[2]) from (
select view_id, time_stamp, [user], RowN = Row_Number() over (partition by [user] order by time_stamp) from #youruser
where issue_event = 'state changed '
) a
pivot (max(time_stamp) for RowN in ([1],[2])) p
输出:
+---------+---------------+-------------------------+-------------------------+----------+
| view_id | user | PauseStart | PauseEnd | IdleTime |
+---------+---------------+-------------------------+-------------------------+----------+
| 6040462 | DerekRoberts | 2017-03-20 02:32:29.000 | 2017-03-20 03:01:03.000 | 29 |
| 6040461 | JamesMorrison | 2017-03-20 02:04:01.000 | 2017-03-20 02:34:11.000 | 30 |
+---------+---------------+-------------------------+-------------------------+----------+
答案 2 :(得分:0)
另一种可能性是带有子查询的OUTER APPLY(下面的示例)。如果您不想捕捉尚未完成的暂停,请将OUTER APPLY更改为CROSS APPLY。
CREATE TABLE #Table (
view_id int,
time_stamp DateTime,
[user] nvarchar(50),
issue_event nvarchar(50),
original_value nvarchar(30),
new_value nvarchar(40))
INSERT INTO #Table
VALUES
(6040462,'2017-03-20 02:00:43','DerekRoberts','Position updated',NULL,NULL)
,(6040461,'2017-03-20 02:04:01','JamesMorrison','state changed','Active','Paused')
,(6040461,'2017-03-20 02:08:33','JamesMorrison','Position updated',NULL,NULL)
,(6040462,'2017-03-20 02:20:42','DerekRoberts','Position updated',NULL,NULL)
,(6040462,'2017-03-20 02:32:29','DerekRoberts','state changed','Active','Paused')
,(6040461,'2017-03-20 02:34:11','JamesMorrison','state changed','Paused','Active')
,(6040461,'2017-03-20 02:36:22','JamesMorrison','Position updated',NULL,NULL)
,(6040462,'2017-03-20 02:52:47','DerekRoberts','Position updated',NULL,NULL)
,(6040462,'2017-03-20 03:01:03','DerekRoberts','state changed','Paused','Active')
,(6040462,'2017-03-21 03:32:29','DerekRoberts','state changed','Active','Paused')
,(6040462,'2017-03-21 04:05:03','DerekRoberts','state changed','Paused','Active')
,(6040461,'2017-03-22 02:04:01','JamesMorrison','state changed','Active','Paused')
SELECT
*
FROM
#Table
SELECT
[user],
CONVERT(nvarchar(10), pausedEvent.time_stamp, 102) ShiftDate,
pausedEvent.time_stamp PauseStart,
activatedEvent.time_stamp PauseEnd,
DATEDIFF(minute, pausedEvent.time_stamp, activatedEvent.time_stamp) IdleTime
FROM
#Table pausedEvent
OUTER APPLY (
SELECT TOP 1
activatedEvent.time_stamp
FROM
#Table activatedEvent
WHERE
activatedEvent.issue_event = 'state changed'
and activatedEvent.original_value = 'Paused'
and activatedEvent.new_value = 'Active'
and activatedEvent.time_stamp > pausedEvent.time_stamp
and activatedEvent.[user] = pausedEvent.[user]
ORDER BY time_stamp
) activatedEvent
WHERE
pausedEvent.issue_event = 'state changed'
and pausedEvent.original_value = 'Active'
and pausedEvent.new_value = 'Paused'
DROP TABLE #Table
请注意,各种选项的性能可能会有所不同,具体取决于可用的索引(我不确定这会有多快)。