是否可以在 T-SQL 中按彼此的差异对行进行分组
Is it possible to group rows by difference to each other in T-SQL
是否可以编写一个 SQL 查询,根据日期时间列值与相邻行值的差异对行进行分组?
让我举个例子...我有一个 SQL 查询是这样的:
SELECT
Id,
StartTime,
EndTime,
datediff(second, max(StartTime), EndTime)) as Duration
FROM Timings
ORDER BY StartTime
returns 结果如下:
| ID | StartTime | EndTime | Duration
| 1 | 2017-10-06 10:59:48 | 2017-10-06 10:59:58 | 10
| 2 | 2017-10-06 11:00:02 | 2017-10-06 11:00:06 | 4
| 3 | 2017-10-06 11:00:15 | 2017-10-06 11:00:22 | 7
| 4 | 2017-10-06 11:00:30 | 2017-10-06 11:00:39 | 9
| 5 | 2017-10-06 15:34:31 | 2017-10-06 15:34:45 | 14
| 6 | 2017-10-06 15:34:48 | 2017-10-06 15:34:56 | 8
| 7 | 2017-10-06 15:34:52 | 2017-10-06 15:34:59 | 7
这里重要的是时间分为两批,前四批都在上午 11 点左右完成,后两批在下午 3 点半左右完成。
我想详细了解每批计时的start/end时间,平均时长,一组计时的个数。为此,我需要一种按批次对时间进行分组的方法,其中批次定义为按开始时间排序时,在一个结束时间和下一个开始时间之间少于 30 秒的时间组。可能吗?
真实情况的一些相关笔记...
- 一个批次唯一真正有区别的特征是一个计时结束和下一个计时开始之间的差距会明显变大。硬编码一个固定的时间限制就可以了。
- 如本例所示,一天可能有多个批次,因此按日期分组已过时。
- 实际上,批次的长度可以从几分钟到几个小时不等,只包含几个时间,也可以包含数千个时间。没有设定批次发生的时间。
- 注意第 6 行和第 7 行的时间。多个时间确实并行重叠,一个结束和下一个开始之间的巨大差距仍然存在,但作为方式识别批次。
在 SQL Server 2012+ 中:
在 common table expression 中使用 window 函数 lag()
获取当前行 starttime
的 datediff()
与 endtime
,然后 sum() over()
使用条件聚合(与硬编码值进行比较)生成 batch
:
;with cte as (
select *
, datediff(second,lag(endtime) over (order by starttime),starttime) as prev_dat
from timings
)
select id, starttime, endtime, duration
, sum(case when coalesce(prev_dat,31)>30 then 1 else 0 end) over (
order by starttime
) as batch
from cte
rextester 演示:http://rextester.com/OVNF90739
returns:
+----+---------------------+---------------------+----------+-------+
| id | starttime | endtime | duration | batch |
+----+---------------------+---------------------+----------+-------+
| 1 | 2017-10-06 10:59:48 | 2017-10-06 10:59:58 | 10 | 1 |
| 2 | 2017-10-06 11:00:02 | 2017-10-06 11:00:06 | 4 | 1 |
| 3 | 2017-10-06 11:00:15 | 2017-10-06 11:00:22 | 7 | 1 |
| 4 | 2017-10-06 11:00:30 | 2017-10-06 11:00:39 | 9 | 1 |
| 5 | 2017-10-06 15:34:31 | 2017-10-06 15:34:45 | 14 | 2 |
| 6 | 2017-10-06 15:34:48 | 2017-10-06 15:34:56 | 8 | 2 |
| 7 | 2017-10-06 15:34:52 | 2017-10-06 15:34:59 | 7 | 2 |
+----+---------------------+---------------------+----------+-------+
您可以按日期时间部分分组
group by DATEPART(StartTime, yyyy) + DATEPART(StartTime, MM) + DATEPART(StartTime, DD)
你还必须改变你 select 以匹配
是否可以编写一个 SQL 查询,根据日期时间列值与相邻行值的差异对行进行分组?
让我举个例子...我有一个 SQL 查询是这样的:
SELECT
Id,
StartTime,
EndTime,
datediff(second, max(StartTime), EndTime)) as Duration
FROM Timings
ORDER BY StartTime
returns 结果如下:
| ID | StartTime | EndTime | Duration
| 1 | 2017-10-06 10:59:48 | 2017-10-06 10:59:58 | 10
| 2 | 2017-10-06 11:00:02 | 2017-10-06 11:00:06 | 4
| 3 | 2017-10-06 11:00:15 | 2017-10-06 11:00:22 | 7
| 4 | 2017-10-06 11:00:30 | 2017-10-06 11:00:39 | 9
| 5 | 2017-10-06 15:34:31 | 2017-10-06 15:34:45 | 14
| 6 | 2017-10-06 15:34:48 | 2017-10-06 15:34:56 | 8
| 7 | 2017-10-06 15:34:52 | 2017-10-06 15:34:59 | 7
这里重要的是时间分为两批,前四批都在上午 11 点左右完成,后两批在下午 3 点半左右完成。
我想详细了解每批计时的start/end时间,平均时长,一组计时的个数。为此,我需要一种按批次对时间进行分组的方法,其中批次定义为按开始时间排序时,在一个结束时间和下一个开始时间之间少于 30 秒的时间组。可能吗?
真实情况的一些相关笔记...
- 一个批次唯一真正有区别的特征是一个计时结束和下一个计时开始之间的差距会明显变大。硬编码一个固定的时间限制就可以了。
- 如本例所示,一天可能有多个批次,因此按日期分组已过时。
- 实际上,批次的长度可以从几分钟到几个小时不等,只包含几个时间,也可以包含数千个时间。没有设定批次发生的时间。
- 注意第 6 行和第 7 行的时间。多个时间确实并行重叠,一个结束和下一个开始之间的巨大差距仍然存在,但作为方式识别批次。
在 SQL Server 2012+ 中:
在 common table expression 中使用 window 函数 lag()
获取当前行 starttime
的 datediff()
与 endtime
,然后 sum() over()
使用条件聚合(与硬编码值进行比较)生成 batch
:
;with cte as (
select *
, datediff(second,lag(endtime) over (order by starttime),starttime) as prev_dat
from timings
)
select id, starttime, endtime, duration
, sum(case when coalesce(prev_dat,31)>30 then 1 else 0 end) over (
order by starttime
) as batch
from cte
rextester 演示:http://rextester.com/OVNF90739
returns:
+----+---------------------+---------------------+----------+-------+
| id | starttime | endtime | duration | batch |
+----+---------------------+---------------------+----------+-------+
| 1 | 2017-10-06 10:59:48 | 2017-10-06 10:59:58 | 10 | 1 |
| 2 | 2017-10-06 11:00:02 | 2017-10-06 11:00:06 | 4 | 1 |
| 3 | 2017-10-06 11:00:15 | 2017-10-06 11:00:22 | 7 | 1 |
| 4 | 2017-10-06 11:00:30 | 2017-10-06 11:00:39 | 9 | 1 |
| 5 | 2017-10-06 15:34:31 | 2017-10-06 15:34:45 | 14 | 2 |
| 6 | 2017-10-06 15:34:48 | 2017-10-06 15:34:56 | 8 | 2 |
| 7 | 2017-10-06 15:34:52 | 2017-10-06 15:34:59 | 7 | 2 |
+----+---------------------+---------------------+----------+-------+
您可以按日期时间部分分组
group by DATEPART(StartTime, yyyy) + DATEPART(StartTime, MM) + DATEPART(StartTime, DD)
你还必须改变你 select 以匹配