2016-06-25 58 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') 

因此,我要檢查是否開始時間和結束時間在所有行的該表涵蓋最小開始時間和該表的最大結束時間之間的整個時間段。 因此,從這些行,很明顯,這是真的。但是,對於下面的一組行,由於它們之間的時間差異,它不會是真的。所以我只想要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,喲爲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) 
相關問題