如何查询连续数据的时间段值?

时间:2010-08-16 13:40:04

标签: sql mysql

我有记录表明作业何时开始以及何时结束。在作业结束之前不会记录结束时间,但是从作业开始时起就存在开始时间。我想要的是知道在给定的时间段内有多少工作正在运行。

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

1 个答案:

答案 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
  ;

当然,这会很快变得非常低效 - 所以你可能想要考虑预先聚合。