我想编写一个查询,该查询将仅使用与活动开始和停止时间相对应的时间戳来计算一天中每个15分钟间隔内发生的活动总量。
这是一个示例数据集:
DATE StartDateTime StopDateTime
2/2/2015 2/2/2015 7:00 2/2/2015 7:25
2/2/2015 2/2/2015 7:20 2/2/2015 7:29
2/2/2015 2/2/2015 7:35 2/2/2015 7:42
2/2/2015 2/2/2015 8:05 2/2/2015 8:14
2/2/2015 2/2/2015 8:16 2/2/2015 8:20
2/2/2015 2/2/2015 8:29 2/2/2015 8:40
2/2/2015 2/2/2015 8:55 2/2/2015 9:25
这就是我想要得到的:
DATE Interval activityTime(min)
2/2/2015 2/2/2015 7:00 15
2/2/2015 2/2/2015 7:15 19
2/2/2015 2/2/2015 7:30 7
2/2/2015 2/2/2015 7:45 0
2/2/2015 2/2/2015 8:00 9
2/2/2015 2/2/2015 8:15 5
2/2/2015 2/2/2015 8:30 10
2/2/2015 2/2/2015 8:45 5
2/2/2015 2/2/2015 9:00 15
2/2/2015 2/2/2015 9:15 10
我一直在寻找一种以所需方式组织数据的方法,这是到目前为止我所能找到的最接近的方法,尽管我无法使其正常工作:
我对SQL还是很陌生,所以对解决方案的任何解释将不胜感激。这也是我关于stackoverflow的第一篇文章,所以请让我知道数据是否不是首选格式,或者是否还有其他问题。谢谢!
假设有一些合理的SQL Server最新版本,这应该是一个好的开始:
-- Some sample data.
declare @Samples as Table ( SampleId Int Identity, Start DateTime, Stop DateTime );
insert into @Samples ( Start, Stop ) values
( '2/2/2015 7:00', '2/2/2015 7:25' ),
( '2/2/2015 7:20', '2/2/2015 7:29' ),
( '2/2/2015 7:35', '2/2/2015 7:42' ),
( '2/2/2015 8:05', '2/2/2015 8:14' ),
( '2/2/2015 8:16', '2/2/2015 8:20' ),
( '2/2/2015 8:29', '2/2/2015 8:40' ),
( '2/2/2015 8:55', '2/2/2015 9:25' );
select * from @Samples;
-- Find the limits and align them to quarter hours.
declare @Min as DateTime;
declare @Max as DateTime;
select @Min = min( Start ), @Max = max( Stop )
from @Samples;
set @Min = DateAdd( minute, -DatePart( minute, @Min ) % 15, @Min );
set @Max = DateAdd( minute, 15 - DatePart( minute, @Max ) % 15, @Max );
select @Min as [Min], @Max as [Max];
-- Go for it.
with QuarterHours ( QuarterStart, QuarterStop )
as (
select @Min, DateAdd( minute, 15, @Min )
union all
select QuarterStop, DateAdd( minute, 15, QuarterStop )
from QuarterHours
where QuarterStop < @Max ),
Overlaps
as ( select QH.QuarterStart, QH.QuarterStop, S.Start, S.Stop,
case
when S.Start <= QH.QuarterStart and S.Stop >= QH.QuarterStop then 15
when S.Start <= QH.QuarterStart and S.Stop < QH.QuarterStop then DateDiff( minute, QH.QuarterStart, S.Stop )
when S.Start > QH.QuarterStart and S.Stop >= QH.QuarterStop then DateDiff( minute, S.Start, QH.QuarterStop )
when S.Start > QH.QuarterStart and S.Stop < QH.QuarterStop then DateDiff( minute, S.Start, S.Stop )
else 0 end as Overlap
from QuarterHours as QH left outer join
@Samples as S on S.Start <= QH.QuarterStop and S.Stop >= QH.QuarterStart )
select QuarterStart, sum( Overlap ) as [ActivityTime]
from Overlaps
group by QuarterStart
order by QuarterStart;
您可以将最后一个更改select
为select * from QuarterHours
或select * from Overlaps
以查看一些中间值。
解释性说明:
您可以使用所需的任何范围(@Min
/ @Max
),我只是从示例数据中获取了它们,以便示例可以运行。出于相同的原因,我使用了一个表变量,出于示例的缘故,无需创建“真实”表。
公用表表达式(CTE)通过递归创建QuarterHours
覆盖所需范围的表。(A号码表或帐簿表也可以被用于产生四分之一小时)。然后,LEFT OUTER JOIN
与所述采样数据被用于定位所有的Overlaps
,如果有的话,每个季度小时。这样可以保留没有活动的四分之一小时。
最后SELECT
总结了结果。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句