我有记录表明作业何时开始以及何时结束。在作业结束之前不会记录结束时间,但是从作业开始时起就存在开始时间。我想要的是知道在给定的时间段内有多少工作正在运行。
declare @data table (
JobId INT IDENTITY(1,1),
StartedAt DATETIME NOT NULL,
EndedAt DATETIME NULL
)
insert into @data (StartedAt, EndedAt)
select '1 Jan 2010 8:00', '1 Jan 2010 8:30'
union select '1 Jan 2010 8:00', '1 Jan 2010 9:00'
union select '1 Jan 2010 8:00', '1 Jan 2010 9:20'
union select '1 Jan 2010 9:00', '1 Jan 2010 9:20'
union select '1 Jan 2010 9:10', NULL
鉴于上述情况,我如何查询每小时运行的作业数量?我希望结果表明在8:00到8:59期间有3个工作正在运行,4个工作在9:00到9:59期间运行,如下所示:
Time period Jobs 08:00..08:59 3 09:00..09:59 4
我可以修改架构,并且我对如何记录数据有一些影响,如果这样可以使查询更简单或更有效.Blockquote
答案 0 :(得分:0)
如果不花费大量时间来解决这个问题,我建议最简单的解决方案是创建一个天数表和一个小时表(然后通过创建笛卡尔联接,您可以得到一个小时和几天的表)例如
天(ondate not null) slots(start_time time not null,end_time no_null)
然后确定在这些插槽中有开始或结束时间的作业数量:
SELECT days.ondate, slots.start_time, slots.end_time, (
SELECT COUNT(*) FROM @data
WHERE (@data.start_time BETWEEN
STR_TO_DATE(
CONCATENATE(DATE_FORMAT(days.ondate, 'YYYYMMDD'),
DATE_FORMAT(slots.start_time,'HH24MISS')),
'YYYYMMDDHH25MISS')
AND
STR_TO_DATE(
CONCATENATE(DATE_FORMAT(days.ondate, 'YYYYMMDD'),
DATE_FORMAT(slots.end_time,'HH24MISS')),
'YYYYMMDDHH25MISS')
) OR (@data.start_time BETWEEN
CONCATENATE(DATE_FORMAT(days.ondate, 'YYYYMMDD'),
DATE_FORMAT(slots.start_time,'HH24MISS')),
'YYYYMMDDHH25MISS')
AND
STR_TO_DATE(
CONCATENATE(DATE_FORMAT(days.ondate, 'YYYYMMDD'),
DATE_FORMAT(slots.end_time,'HH24MISS')),
'YYYYMMDDHH25MISS')
) AS jobs_running
FROM days, slots
;
当然,这会很快变得非常低效 - 所以你可能想要考虑预先聚合。