在整个时间范围内生产岛屿.SQL Server

Dan*_*ell 5 sql sql-server gaps-and-islands

请帮帮我,我有一个奇怪的SQL问题.

因此,如果您假设标准办公时间在9:00到17:00之间.

我有一个休息列表,我想将这些休息时间添加到我的工作日,并在我可用时返回一系列休息时间.

这个SQL显示了我的工作时间,休息时间以及我希望输出的内容:

DECLARE @WorkingHours TABLE
   (StartTime TIME, EndTime TIME, EventDate date, IsBreak bit)
insert @WorkingHours select '09:00',  '17:00', '2018-08-15', 0;

DECLARE @Breaks TABLE
   (StartTime TIME, EndTime TIME, EventDate date, IsBreak bit)

insert @Breaks select '11:30',  '12:30', '2018-08-15', 1;
insert @Breaks select '12:00',  '13:00', '2018-08-15', 1;
insert @Breaks select '15:00',  '16:00', '2018-08-15', 1;
insert @Breaks select '15:25',  '15:55', '2018-08-15', 1;
insert @Breaks select '09:50',  '10:05', '2018-08-15', 1;
insert @Breaks select '15:50',  '16:05', '2018-08-15', 1;

DECLARE @Output TABLE
   (StartTime TIME, EndTime TIME, EventDate date)

insert @Output select '09:00',  '09:50', '2018-08-15';
insert @Output select '10:05',  '11:30', '2018-08-15';
insert @Output select '13:00',  '15:00', '2018-08-15';
insert @Output select '16:05',  '17:00', '2018-08-15';

SELECT * FROM @Output
Run Code Online (Sandbox Code Playgroud)

这是我设法来的最接近的,但它不处理重叠中断或休息时间的中断.

DECLARE @Final TABLE
   (StartTime TIME, EndTime TIME, EventDate date, IsBreak bit)

INSERT INTO @Final
SELECT * FROM @WorkingHours
UNION
SELECT * FROM @Breaks

SELECT CASE WHEN t1.IsBreak = 0 THEN t1.StartTime  
            ELSE t1.EndTime 
        END AS StartTime , 
       CASE WHEN LEAD(t1.EventDate) OVER 
                   ( ORDER BY t1.EventDate, 
                              t1.[StartTime]
                   ) = t1.EventDate THEN 
                     coalesce(Lead(t1.StartTime) OVER
                       ( ORDER BY t1.EventDate, 
                                  t1.[StartTime]), 
                                  '17:00'
                       ) 
            ELSE '17:00' 
        END AS EndTime, 
        t1.EventDate 
  FROM  @Final  t1 
 INNER 
  JOIN @Final t2 
    ON t1.EventDate = t2.EventDate 
   AND t2.IsBreak = 0 
Run Code Online (Sandbox Code Playgroud)

任何人都可以提供的任何帮助将不胜感激.

Kob*_*obi 1

可以通过使用 过滤最后一个查询的结果来获得所需的输出StartTime < EndTime,例如使用 cte :

WITH cte AS ( SELECT     CASE
                           WHEN t1.IsBreak = 0 THEN t1.StartTime
                           ELSE t1.EndTime
                         END   AS StartTime
                       , CASE WHEN LEAD(t1.EventDate) OVER ( ORDER BY t1.EventDate, t1.[StartTime]) = t1.EventDate 
                              THEN COALESCE(LEAD(t1.StartTime) OVER( ORDER BY t1.EventDate, t1.[StartTime]), '17:00') 
                              ELSE 
                                '17:00' 
--           (
--               SELECT MAX(EndTime)
--               FROM @Final
--               WHERE IsBreak = 0
--                     AND [@Final].EventDate = t1.EventDate
--           )

                             END AS EndTime
                           , t1.EventDate
                  FROM       @Final t1
                  INNER JOIN @Final t2
                          ON t1.EventDate = t2.EventDate
                         AND t2.IsBreak   = 0 )
    SELECT *
    FROM   cte
    WHERE  StartTime < EndTime 
Run Code Online (Sandbox Code Playgroud)