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 和 EndTime 是否涵盖了该表的 Minimum StartTime 和 Maximum 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')

我已经设法完成了所有其他任务,这是他们的最终结果。这是最后的任务,我完全不知道该怎么做。任何帮助,将不胜感激。

4

4 回答 4

2

通常间隔可以是任意长度,因此比较相邻行远非完整的解决方案。除了上面评论中引用的 Itzik Ben-Gan 的 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)
于 2016-06-25T16:12:55.533 回答
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
于 2016-06-25T12:23:50.100 回答
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
于 2016-06-25T14:01:13.113 回答
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
于 2016-06-25T14:31:38.007 回答