在特定时间之间查找时间表数据中的差距

时间:2017-08-01 17:23:37

标签: sql-server tsql sql-server-2012

我正试图在上午8点到下午6点之间找出时间表中的空白。我能够找到记录的记录的空白,但我无法弄清楚如何确定记录是否“错过” - 这意味着如果他们在上午8:30开始,我无法弄清楚如何识别30分钟的差距上午8点到8点30分(即他们开始工作到很晚)。

在下面的例子中,我可以找到12点到12点30分之间的两个差距,但不是早上8点到8点30分的差距和5点8分和早上8点到早上6点的差距。 5/10。

有任何想法指出我如何处理这个方向的正确方向?

drop table #time;
create table #time (
    TimesheetId int not null
    , StartTime datetime not null
    , EndTIme datetime not null
);

insert into #time (TimesheetId, StartTime, EndTime)
    values (210, '2017-05-08 05:30:00.000', '2017-05-08 06:30:00.000')
         , (210, '2017-05-08 06:30:00.000', '2017-05-08 08:30:00.000')
         , (210, '2017-05-08 08:30:00.000', '2017-05-08 12:00:00.000')
         , (210, '2017-05-08 12:30:00.000', '2017-05-08 18:30:00.000')
         , (210, '2017-05-09 08:30:00.000', '2017-05-09 12:00:00.000')
         , (210, '2017-05-09 12:30:00.000', '2017-05-09 17:30:00.000')
         , (210, '2017-05-09 22:30:00.000', '2017-05-10 05:30:00.000')
         , (210, '2017-05-10 08:30:00.000', '2017-05-10 18:00:00.000')
;

; with t1 as (
    SELECT TimesheetId
         , StartTime
         , lag(EndTime) OVER (PARTITION BY TimesheetId ORDER BY StartTime) AS prev_endtime
    FROM #time
    where datepart(HH, StartTime) <= 18
        and datepart(HH, EndTime) >= 8
)
select prev_endtime as gapStart
     , StartTime as gapEnd
from t1
where StartTime <> prev_endtime
and cast(prev_endtime as date) = cast(StartTime as date)
;

2 个答案:

答案 0 :(得分:2)

WITH
  a AS(SELECT DATEADD(hh, DATEDIFF(dd, 0, StartTime) * 24 + 8, 0) t,
         TimesheetId FROM #time),
  b AS(SELECT * FROM #time UNION ALL SELECT TimesheetId, t, t FROM a UNION ALL
       SELECT TimesheetId, DATEADD(hh, 10, t), DATEADD(hh, 10, t) FROM a),
  c AS(SELECT TimesheetId,
         LAG(EndTime) OVER (
           PARTITION BY TimesheetId ORDER BY StartTime
         ) prev_fin,
         StartTime
       FROM b),
   d AS(SELECT *, DATEADD(hh, DATEDIFF(dd, 0, prev_fin) * 24 + 8, 0) beg,
          DATEADD(hh, DATEDIFF(dd, 0, prev_fin) * 24 + 18, 0) fin
        FROM c)
SELECT TimesheetId, prev_fin, StartTime
FROM d
WHERE prev_fin < StartTime AND
  ((prev_fin >= beg AND prev_fin < fin) OR
   (StartTime > beg AND StartTime <= fin));

rextester.com上查看。

答案 1 :(得分:0)

您可以使用它来插入记录,然后使用您拥有的内容 或者你可以使用UNION

select distinct t1.TimesheetId, dateadd(hh, 8, cast(CONVERT(date, StartTime) as datetime)) as StartTime, dateadd(hh, 8, cast(CONVERT(date, StartTime) as datetime)) as EndTime
  from #time t1  
 where not exists ( select dateadd(hh, 8, cast(CONVERT(date, T2.StartTime) as datetime)), t2.* 
                     from #time T2 
                    where 1 = 1 
                      and t2.TimesheetId = t1.TimesheetId 
                      and CONVERT(date, T2.StartTime) = CONVERT(date, T1.StartTime)
                      and t2.StartTime = dateadd(hh, 8, cast(CONVERT(date, t2.StartTime) as datetime)) 
                  )