根据当前行和下一行汇总行

时间:2017-04-02 06:50:24

标签: sql sql-server

我有以下格式的输入: Input Image

我必须找到当前行的停止和下一行的开始之间的差异,如果差异小于25,我需要对[TimeDiff_Start_Stop]中的值求和。如果差异超过25,我不需要做总和。

如上图所示,差异

第1行停止和第2行开始之间的

是13, 在第2行的停止和第3行的开始之间是2, 在第3行的停止和第4行的开始之间是1, 在第4行的停止和第5行的开始之间是3, 在第5行的停止和第6行的开始之间是8,
但第6行的停止和第7行的开始之间的区别是37, 因此,只对前6行的[TimeDiff_Start_Stop]求和,从而在输出中产生第1行。

第7行停止和第8行开始之间的进一步差异是20, 因此,第7行和第8行的[TimeDiff_Start_Stop]相加,在输出中产生第2行。

必需的输出

Output Image

我该如何实现这个目标?

请在下面找到输入和输出脚本:

输入:

select 'Sample' as COL1,'1' AS COL2,1 as 'RN','2016-05-09 02:45:18.239669' AS Start,'2016-05-09 02:45:25.837316' as Stop,7 as TimeDiff_Start_Stop
union
select 'Sample' as COL1,'1' AS COL2,2 as 'RN','2016-05-09 02:45:38.809919' AS Start,'2016-05-09 02:46:59.856081' as Stop,81 as TimeDiff_Start_Stop
union
select 'Sample' as COL1,'1' AS COL2,3 as 'RN','2016-05-09 02:47:01.831128' AS Start,'2016-05-09 02:48:55.211807' as Stop,114 as TimeDiff_Start_Stop
union
select 'Sample' as COL1,'1' AS COL2,4 as 'RN','2016-05-09 02:48:56.305736' AS Start,'2016-05-09 02:50:06.107262' as Stop,70 as TimeDiff_Start_Stop
union
select 'Sample' as COL1,'1' AS COL2,5 as 'RN','2016-05-09 02:50:09.269354' AS Start,'2016-05-09 02:50:16.081159' as Stop,7 as TimeDiff_Start_Stop
union
select 'Sample' as COL1,'1' AS COL2,6 as 'RN','2016-05-09 02:50:24.819440' AS Start,'2016-05-09 02:51:04.736300' as Stop,40 as TimeDiff_Start_Stop
union
select 'Sample' as COL1,'1' AS COL2,7 as 'RN','2016-05-09 02:51:41.029165' AS Start,'2016-05-09 02:54:04.186215' as Stop,143 as TimeDiff_Start_Stop
union
select 'Sample' as COL1,'1' AS COL2,8 as 'RN','2016-05-09 02:54:24.537167' AS Start,'2016-05-09 02:55:26.926029' as Stop,62 as TimeDiff_Start_Stop

输出:

select 'Sample' as COL1,'1' AS COL2,'2016-05-09 02:45:18.239669' AS Start,'2016-05-09 02:51:04.736300' as Stop,319 as Time
union
select 'Sample' as COL1,'1' AS COL2,'2016-05-09 02:51:41.029165' AS Start,'2016-05-09 02:55:26.926029' as Stop,205 as Time

1 个答案:

答案 0 :(得分:3)

以下是两种不同的方法 - 为此,我创建了一个表@t并使用您的示例数据来填充它 - 感谢您证明这些。这是表格定义:

data.item.Feature.some(function(x) { return x.Type.ID === 6508 });

这是使用CTE的方法。首先,它创建一个CTE,它只是添加diff(使用LEAD来获取当前行停止/下一行开始之间的差异)作为列。

注意如果没有后续行,CTE查询中的isnull语句将值26赋给null - 这意味着结果集中的最后一行获取值为26(> 25,因此将匹配条件一行应该是结果集中的结束时间。)

declare @t table (col1 varchar(10), col2 int, rn int, start datetime2, stop datetime2, timediff_start_stop int)
insert into @t ... (from the OP)

接下来,这是一个使用游标的完全不同的解决方案。游标效率低,不太适合频繁运行的任务,但我发现它们很容易维护并且作为开发人员遵循,并且认为它可能对需要运行适合游标的不常见或一次性任务的人有用:

;with tdiff (col1, col2, rn, start, stop, timediff_start_stop, diff, timediff)
as
(
select col1, col2, rn, start, stop, timediff_start_stop, isnull(datediff(ss, stop, lead(start) over (order by rn)), 26) as diff, datediff(ss, start, stop)
from @t
)
select t1.col1, t1.col2, t1.start, (select min(stop) from tdiff where stop > t1.start and diff > 25) as stop, 
    (select sum(timediff_start_stop) from tdiff where start >= t1.start and stop <= (select min(stop) from tdiff where stop > t1.start and diff > 25)) AS TIME
from tdiff t1
left join tdiff t2 on (t1.rn - 1) = t2.rn
where t1.rn = 1 or t2.diff > 25