一尘不染

获取记录组之间的时间差

sql

我有一个具有以下结构的表

ID         ActivityTime             Status
19        2013-08-23 14:52            1
19        2013-08-23 14:50            1
19        2013-08-23 14:45            2
19        2013-08-23 14:35            2
19        2013-08-23 14:32            1
19        2013-08-23 14:30            1
19        2013-08-23 14:25            2
19        2013-08-23 14:22            2
53        2013-08-23 14:59            1
53        2013-08-23 14:56            1
53        2013-08-23 14:57            1
53        2013-08-23 14:52            2
53        2013-08-23 14:50            2
53        2013-08-23 14:49            2
53        2013-08-23 14:18            2
53        2013-08-23 14:30            1

我想针对状态2计算每个ID的总时差。例如,ID
19停留在状态2上的时间是从14:35到14:50(15分钟),然后是14:22到14:30(8分钟)。因此,停留在状态2上的总ID 19为23分钟。
(在两种情况下,我都考虑了从状态2到状态1的最短时间) 问题是 我如何仅包括状态之间的差异,而 下一行 中它们是不同的。

例如,我将排除状态为1的表中的第一条记录,然后选择第二行。与状态2相同。我会选择最短时间,计算它们之间的差异,然后针对每个通道将它们添加为多组状态。

我尝试使用CURSOR,但似乎无法使其正常工作。我也非常有信心,在获取所有数据然后循环遍历之后,我可以在C#中实现这一目标。但是我只是想知道是否存在直接获得信息而无需循环的方法。我还
用数据创建了一个SQL提琴,但是我似乎无法使其正常工作。我来自具有SQL基本知识的C#背景。如果有人能帮助我会很高兴。


阅读 131

收藏
2021-05-23

共1个答案

一尘不染

CTE(通用表表达式)可以像专用的临时表一样使用。它允许您(在这种情况下)动态创建行号,以后可以在其上创建自我联接。

我认为您正在寻找这样的东西:

--create temp table
select 19 as id,'2013-08-23 14:52' as activitytime,1 as status
into #temp
union all
select 19,'2013-08-23 14:50',1 union all
select 19,'2013-08-23 14:45',2 union all
select 19,'2013-08-23 14:35',2 union all
select 19,'2013-08-23 14:32',1 union all
select 19,'2013-08-23 14:30',1 union all
select 19,'2013-08-23 14:25',2 union all
select 19,'2013-08-23 14:22',2 union all
select 53,'2013-08-23 14:59',1 union all
select 53,'2013-08-23 14:56',1 union all
select 53,'2013-08-23 14:57',1 union all
select 53,'2013-08-23 14:52',2 union all
select 53,'2013-08-23 14:50',2 union all
select 53,'2013-08-23 14:49',2 union all
select 53,'2013-08-23 14:18',2 union all
select 53,'2013-08-23 14:30',1

--build cte table
;WITH cte
AS (
SELECT 
    *,
    ROW_NUMBER() OVER (ORDER BY  id, activitytime) AS RowNum
FROM 
    #temp
)

--query cte table, self joining row 1 to row 2 to compare.
SELECT a.id, sum(DATEDIFF(minute,b.ActivityTIme,a.ActivityTime)) as TotalTime
FROM 
 cte AS A
 LEFT OUTER JOIN cte AS B   
 ON A.RowNum = B.RowNum + 1 and a.id = b.id
where b.status = 2
group by a.id
2021-05-23