2015-12-18 3 views
1

у меня есть что-то вроде этогоГруппировка последовательных интервалов времени в SQL

+------+-----+-----------+---------+ 
| Room | Day | StartTime | EndTime | 
+------+-----+-----------+---------+ 
| 1 | 1 | 08:00  | 09:00 | 
+------+-----+-----------+---------+ 
| 1 | 1 | 09:00  | 10:00 | 
+------+-----+-----------+---------+ 
| 1 | 1 | 13:00  | 14:00 | 
+------+-----+-----------+---------+ 
| 2 | 2 | 07:00  | 08:00 | 
+------+-----+-----------+---------+ 

Я хочу группы по комнате, день и временной интервал, но только последовательные интервалы времени, например:

+------+-----+-----------+---------+ 
| Room | Day | StartTime | EndTime | 
+------+-----+-----------+---------+ 
| 1 | 1 | 08:00  | 10:00 | 
+------+-----+-----------+---------+ 
| 1 | 1 | 13:00  | 14:00 | 
+------+-----+-----------+---------+ 
| 2 | 2 | 07:00  | 08:00 | 
+------+-----+-----------+---------+ 

У меня есть этот код, но я не удовлетворен, потому что также группирует промежутки и генерирует следующий результат:

SELECT 
sd.Cod_Room, 
sd.Cod_Day, 
MIN(bd.StartTime) as StartTime, 
MAX(bd.EndTime) as EndTime 
FROM 
Schedule.ScheduleDetail AS sd 
INNER JOIN Schedule.BlockDetail AS bd ON sd.Cod_BlockDetail = bd.Cod_BlockDetail 
GROUP BY 
sd.Room, sd.Day 

+------+-----+-----------+---------+ 
| Room | Day | StartTime | EndTime | 
+------+-----+-----------+---------+ 
| 1 | 1 | 08:00  | 14:00 | 
+------+-----+-----------+---------+ 
| 2 | 2 | 07:00  | 08:00 | 
+------+-----+-----------+---------+ 

Я читал о lead() и lag(), но мне нужно больше времени, чем я думал. Я ценю вашу помощь

+0

Какую версию сервера sql вы используете? – JamieD77

+0

@ JamieD77 Я использую 2014 –

ответ

3

Вы можете сделать это, указав группы, которые перекрываются, а затем накапливают это значение для определения группы. Ниже приведен пример SQL Server 2012+:

with t as (
     select sd.Cod_Room, sd.Cod_Day, bd.StartTime, bd.EndTime 
     from Schedule.ScheduleDetail sd INNER JOIN 
      Schedule.BlockDetail bd 
      ON sd.Cod_BlockDetail = bd.Cod_BlockDetail 
    ) 
select cod_room, cod_day, 
     min(startTime) as startTime, max(endTime) as endTime 
from (select t.*, 
      sum(IsStart) over (partition by cod_room, cod_day order by StartTime) as grp 
     from (select t.*, 
        (case when StartTime = lag(EndTime) over (partition by cod_room, cod_day order by StartTime) 
         then 0 else 1 
        end) as IsStart 
      from t 
      ) t 
    ) t 
group by cod_room, cod_day, grp; 
+0

Отлично! Он работает безупречно! –

Смежные вопросы