1

我有一个包含开始日期(日期时间)和结束日期(日期时间)的数据库表。此表包含活动持续时间。现在我正在尝试创建一个函数来计算基于指定 begindate-enddate 内的非重叠活动的总持续时间。

一个例子如下:

我正在调用此函数并提供参数: Begindate='2012-08-16 10:00' Enddate='2012-08-16 18:00'

现在假设表中有以下数据:

  1. 开始:“2012-08-15 10:00”结束“2012-08-15 14:00”(共 4 小时)
  2. 开始:“2012-08-16 09:00”结束“2012-08-16 11:00”(共 2 小时)
  3. 开始:“2012-08-16 10:30”结束“2012-08-16 10:45”(共 15 分钟)
  4. 开始:“2012-08-16 12:00”结束“2012-08-16 16:00”(共 4 小时)
  5. 开始:“2012-08-16 13:00”结束“2012-08-16 17:00”(共 4 小时)
  6. 开始:“2012-08-16 16:30”结束“2012-08-16 16:45”(共 15 分钟)
  7. begin: '2012-08-16 17:30' end '2012-08-16 20:00' (共 2 小时 30 分钟)

现在我希望发生以下情况:

  1. 第一项活动超出指定期限,因此不包括在内。
  2. 部分匹配,因此这将返回 1 小时。
  3. 活动在第二个活动中,因此不包括在内。
  4. 包括期间内的 4 小时。
  5. 16:00 至 17:00 包含 1 小时
  6. 活动将不包括在内。
  7. 指定时间段内只有 30 分钟,因此将包括在内。

返回的总时间为:6 小时 30 分钟。

如果有人可以帮助我,我将不胜感激!:)

4

1 回答 1

3

计算缺失范围然后从完整期间中减去持续时间可能更容易:

declare @begindate datetime = '20120816 10:00:00'
declare @enddate datetime = '20120816 18:00:00'

; with supplement as (
  select begindate, enddate
    from daterangetable
      -- overlapping ranges only
   where begindate <= @enddate
     and enddate >= @begindate
  union all
  -- empty start range to catch missing start intervals
  select @begindate, @begindate
  union all
  -- empty end range to catch missing end intervals
  select @enddate, @enddate
)
select datediff (minute, @begindate, @enddate)
     - sum (datediff (minute, gapStart, gapEnd)) Minutes
from
(
  select max(d2.enddate) gapStart, 
         d1.begindate gapEnd
    from supplement d1
   cross join supplement d2
      -- d2 range must start before d1 range
   where d2.begindate < d1.begindate
   group by d1.begindate
      -- Range is completely covered if d2 ends after d1 begins
      -- so it should be removed
  having max(d2.enddate) < d1.begindate
) missingRanges

如果第一个结束在第二个开始之后并且第一个开始在第二个结束之前,则两个范围重叠。请参阅链接以获得(更好的)解释。

如果您使用的不是 Sql Server 2005 或更新版本,则需要将内部代码移动with到派生表中,用于补充 d1 和补充 d2。

这是带有示例的 Sql Fiddle

于 2012-08-16T09:48:44.060 回答