2016-06-25 5 views
2

У меня есть таблица, в которой есть два столбца StartTime и EndTime. Значения заполняются в нем, как:Как проверить, охватывает ли заданные строки весь временной диапазон

declare @tbl Table(
colA VARCHAR(50), 
colS VARCHAR(50), 
DATES DATE, 
STARTTIME TIME, 
ENDTIME TIME, 
ID BIGINT NOT NULL IDENTITY(1,1) 
) 

INSERT INTO @tbl 
SELECT 'A','S',convert(date,'2015-09-21'),convert(TIME,'12:45'),convert(TIME,'13:30') 
UNION ALL 
SELECT 'A','S',convert(date,'2015-09-21'),convert(TIME,'13:15'),convert(TIME,'13:45') 
UNION ALL 
SELECT 'A','S',convert(date,'2015-09-21'),convert(TIME,'13:30'),convert(TIME,'16:50') 
UNION ALL 
SELECT 'A','S',convert(date,'2015-09-21'),convert(TIME,'13:15'),convert(TIME,'13:50') 

Таким образом, я хочу, чтобы проверить, является ли StartTime и Конечное время во всех строках этой таблицы охватывает весь период времени между минимальной StartTime и максимальной EndTime этой таблицы. Следовательно, из этих строк ясно, что это правда. Однако для следующего набора строк это не будет истинным из-за временного промежутка в них. Поэтому в результате я просто хочу True или False.

INSERT INTO @tbl 
SELECT 'A','S',convert(date,'2015-09-21'),convert(TIME,'08:45'),convert(TIME,'09:15') 
UNION ALL 
SELECT 'A','S',convert(date,'2015-09-21'),convert(TIME,'11:10'),convert(TIME,'11:25') 

Мне удалось выполнить все остальные задачи, и это их конечный результат. Это заключительная задача, и я совершенно не знаю, как это сделать. Любая помощь будет оценена по достоинству.

+1

[Упаковка Интервалы Ицик Бен-Ган] (http://blogs.solidq.com/en/sqlserver/packing-intervals/) –

ответ

1

- Последняя колонка будет 1 с вашими данными первого примера и 0 с лет ур второй.

SELECT t.*, 
    CASE WHEN t.ENDTIME < m.MaxStartTime THEN 0 
     WHEN t.STARTTIME > m.MinEndTime THEN 0 
     ELSE 1 END AS Covered 
    FROM @tbl AS t 
    JOIN 
     (SELECT DATES, 
       MIN(ENDTIME) MinEndTime, 
       MAX(STARTTIME) MaxStartTime 
       FROM @tbl 
       GROUP BY DATES) AS m 
    ON t.DATES = m.DATES 
1

попробовать

;with a as (select *,row_number() over (order by DATES,starttime) rn from @tbl) 

select a.*, 
case when isnull(b.endtime,a.endtime)>=a.STARTTIME then 'true' else 'false' end 
from a left join a b on a.rn=b.rn+1 
+0

Спасибо за ответ, но у меня есть SQL Server 2008 и не 2012, поэтому я не думаю, что отставание и ведущая работа в sql 2008. –

+0

попробуйте обновленный запрос на самостоятельное присоединение, у меня есть только sql 2012 со мной – nazark

1

Если есть достаточно, чтобы проверить, если интервал времени следующей строки является переход к следующему интервалу строки, то OUTER APPLY должны делать вещи для вас:

SELECT t.*, 
     CASE WHEN t.ENDTIME between p.STARTTIME and p.ENDTIME OR p.ENDTIME IS NULL THEN 'TRUE' ELSE 'FALSE' END as Seq 
FROM @tbl t 
OUTER APPLY (
    SELECT TOP 1 * 
    FROM @tbl 
    WHERE t.STARTTIME < STARTTIME and t.colA = colA and t.colS = colS and t.DATES = DATES 
    ORDER BY STARTTIME ASC) p 
ORDER BY t.STARTTIME 

Выход для данного материала :

colA colS DATES  STARTTIME   ENDTIME    ID Seq 
A  S  2015-09-21 08:45:00.0000000 09:15:00.0000000 5 FALSE 
A  S  2015-09-21 11:10:00.0000000 11:25:00.0000000 6 FALSE 
A  S  2015-09-21 12:45:00.0000000 13:30:00.0000000 1 TRUE 
A  S  2015-09-21 13:15:00.0000000 13:45:00.0000000 2 TRUE 
A  S  2015-09-21 13:15:00.0000000 13:50:00.0000000 4 TRUE 
A  S  2015-09-21 13:30:00.0000000 16:50:00.0000000 3 TRUE 
2

Обычно интервалы могут быть любой длины, поэтому сравнение соседних строк далека от полного решения. Кроме того, решение Itzik Ben-Gan's Packing Intervals, приведенное выше, еще одно полное решение - проверять каждую минуту (или другую гранулярность).

select uncoverdMinutes=count(*) -- 0 is true 
from(
    select colA, colS, t.m 
    from ( 
     select colA, colS 
      , mst = min(starttime) 
      , cnt = datediff(minute, min(starttime), max(endtime)) + 1 
     from @tbl 
     group by colA, colS 
    ) prm 
    cross apply (
     select top(prm.cnt) 
      m = dateadd(minute 
         ,row_number() over(order by (select null)) - 1 
         ,prm.mst)          
     from sys.all_objects -- use tally table instead, if you have one 
     ) t 
) mi 
where not exists (
    select 1 
    from @tbl t 
    where mi.m between t.starttime and t.endtime)