检查计划是否在天之间重叠

时间:2011-05-11 14:07:17

标签: sql sql-server sql-server-2005

我需要查找新计划是否与任何现有计划重叠。

这是“间隔”表:

     id  first              last    
     1   1900-01-01 09:00   1900-01-01 10:00
     2   1900-01-01 15:00   1900-01-01 18:00
     3   1900-01-01 18:01   1900-01-01 08:00

我正在使用标量函数 dbo.TimeOnly 从日期时间字段中提取时间部分。

我的选择标准如下

第一个案例

     declare @start datetime
     declare @end datetime

     set @start = dbo.TimeOnly('2011-may-11 08:01:00');
     set @end = dbo.TimeOnly('2011-may-11 15:30:00');

     select  * from intervals where 
     ( NOT ( dbo.TimeOnly(last) < @start OR  @end < dbo.TimeOnly(first) ) )

这将返回第1和第2条记录。我从Check whether the schedule overlaps each other?

得到了这个逻辑

第二种情况

    set @start = dbo.TimeOnly('2011-may-11 07:01:00');
    set @end = dbo.TimeOnly('2011-may-11 08:30:00');

如何编写一个只返回第二种情况下条件的第3条记录的查询?

更新

我会提供更多有关我的问题的详细信息

不同的人在一天中管理特定事件一段时间。

对于星期一,计划格式如下

    Id  Start       End          User   Days    
     1  00:01 AM    08:00 AM     'A'    1
     2  08:01 AM    04:00 PM     'B'    1
     3  04:00 PM    00:00 AM     'C'    1

星期二

     4  08:01 AM    04:00 PM     'B'    2
     5  07:00 PM    07:00 AM     'C'    2

星期三

     6  08:01 AM    04:00 PM     'A'    4
     7  10:00 PM    08:00 AM     'B'    4

这里的日子以比特值格式存储,即

周一= 1,周二= 2,周三= 4,周四= 8,周五= 16,周六= 32,周日= 64

当我们为特定日期创建计划时,它不应在时间之间重叠。 我希望获得一个SQL查询,以便在为特定日期创建新计划时检查是否存在任何计划。

对于特定的活动时间( Say An偶然发生在星期二凌晨04:00 )我想找到介于开始和结束之间的正确时间表(将是“5”)时间。

2 个答案:

答案 0 :(得分:0)

你需要做这样的事情:

Declare @start datetime
Declare @duration int

Set @start = dbo.TimeOnly('2011-May-11 07:01:00');
-- Get the number of minutes in your timespan
Set @duration = DateDiff(minute, '2011-May-11 07:01:00', '2011-May-12 08:30:00');

Select id, first, last
From intervals
Where (DateDiff(minute, dbo.TimeOnly(first)), @start) + @duration) > 0
AND DateDiff(minute, dbo.TimeOnly(first), @start) <
 DateDiff(minute, dbo.TimeOnly(first), dbo.TimeOnly(last));

假设您的dbo.TimeOnly功能与Convert(time, {timefield})基本相同。

这将首先找到新开始时间与现有开始时间之间的差异,然后将查明新时段的持续时间是否长于该差异。这涵盖了在现有之前或期间开始的新时期。

最后一句将新开始时间与现有开始时间之间的差异与现有时间段的持续时间进行比较,以检查现有时间段是否长于它们之间的差异。否则,新的开始时间自然会在现有的结束时间之后,这意味着它不会重叠。

答案 1 :(得分:0)

将SELECT更改为:

select  * from intervals where 
(
( dbo.TimeOnly(last) > dbo.TimeOnly(first)
AND
NOT (dbo.TimeOnly(last) < @start OR  @end < dbo.TimeOnly(first)) )

OR

( dbo.TimeOnly(last) < dbo.TimeOnly(first)
AND
( @start >= dbo.TimeOnly(first) OR @end <= dbo.TimeOnly(last) OR (@start < dbo.TimeOnly(first) AND @end > dbo.TimeOnly(last)) ) )
)

我可能错过了某个地方的括号,但我希望不会。

这里的概念是一个包含2个主要分组和OR的查询。第一个子句检查 last>的间隔。第一个,主要是现有查询的副本,添加 last&gt;第一个条件,而第二个子句检查 last&lt;第一

在最后&lt;首先,间隔可以有3种方式重叠:

  • start是在间隔的第一个
  • 之后
  • end在间隔的最后一个
  • 之前
  • 开始和结束完全吞没了间隔,即,开始是在第一个之前,结束是在最后一个
  • 之后

这3个条件中的任何一个都意味着要检查的时间表在现有的时间间隔内,因此3个条件与OR组合。