Sql Fnd培训师可安排的具有规定跨度的连续日期

Sql Fnd培训师可安排的具有规定跨度的连续日期,sql,tsql,sql-server-2005,schedule,date-range,Sql,Tsql,Sql Server 2005,Schedule,Date Range,我们有一个表,用于为计划的客户安装分配培训师。在表格中,每个培训师每年的每一天都有一个记录。我们可以,有时也可以,周末工作。我正在建立一个搜索工具,允许我们的调度员搜索在日期Y和Z之间X天内可用的培训师 Table mySchedule Trainer Date Dirty (Bit) ------------------------------------------------ Joe 06/01/2013

我们有一个表,用于为计划的客户安装分配培训师。在表格中,每个培训师每年的每一天都有一个记录。我们可以,有时也可以,周末工作。我正在建立一个搜索工具,允许我们的调度员搜索在日期Y和Z之间X天内可用的培训师

Table mySchedule

Trainer        Date       Dirty (Bit)
------------------------------------------------                
Joe         06/01/2013      0
Jessica     06/01/2013      0
Alan        06/01/2013      0
Heather     06/01/2013      0
Joe         06/02/2013      1
Jessica     06/02/2013      1
Alan        06/02/2013      0
Heather     06/02/2013      0
Joe         06/03/2013      1
Jessica     06/03/2013      1
Alan        06/03/2013      1
Heather     06/03/2013      0
这是我表格的简化版本,涵盖了三天内的四名培训师。如果他们安排了一些事情,Dirty=1。如果他们可以自由安排,则Dirty=0

我想要构建的是一个查询,它允许以下内容:

定义工作需要发生的开始和结束日期

定义培训师需要的连续天数

返回每个匹配的培训师,以及他们在至少等于请求天数的时间段内的第一个可用日期

纯文本示例:

客户要求培训师在6月份的任何时候在现场工作两天。查询应返回:

Alan, 06/01/2013
Heather, 06/01/2013
Heather, 06/01/2013
如果客户将请求更改为6月的3天,则查询将返回:

Alan, 06/01/2013
Heather, 06/01/2013
Heather, 06/01/2013
我已经找了几天了,我发现了一些似乎很接近的东西,但最终,我无法让它们发挥作用。在大多数情况下,失败的形式是执行时间过长。以下是一些看起来很有希望的,并且可能可以被比我更强大的SQL Fu的人采用:


假设丢失的计划记录默认为可用,类似这样的操作应该有效:

WITH cteRawData As
(
   SELECT
      S.Trainer,
      S.Date,

      -- If there are no later busy dates within the period,
      -- assume they're free until the end of the period:
      IsNull(ED.EndDate, DateAdd(day, 1, @EndDate)) As EndDate
   FROM
      mySchedule As S
      CROSS APPLY
      (
         SELECT
            Min(Date) As EndDate
         FROM
            mySchedule As S2
         WHERE
            S2.Trainer = S.Trainer
         And
            S2.Date > S.Date
         And
            S2.Date <= @EndDate
         And
            S2.Dirty = 1
      ) As ED
   WHERE
      S.Date Between @StartDate And @EndDate
   And
      S.Dirty = 0
),
cteData As
(
   SELECT
      Trainer,
      Date,
      DateDiff(day, Date, EndDate) As NumberOfDays
   FROM
      cteRawData
)
SELECT
   Trainer,
   Min(Date) As EarliestStartDate
FROM
   cteData
WHERE
   NumberOfDays >= @NumberOfDays
GROUP BY
   Trainer
;

不确定这将如何在较大的数据集上执行,但它会为提供的数据集获得正确的结果。假设缺失的数据点可用

declare @startDate datetime, @endDate datetime, @days int
select @startDate = '6/1/2013', @endDate='6/3/2013', @days=2

select trainer, min(date)
from
    (
    select  trainer,date,
            (select top 1 date
            from mySchedule sInner
            where sInner.date > sOuter.date
                    and sInner.trainer = sOuter.trainer
                    and sInner.Dirty = 1    
                    and sInner.date between @startDate and @endDate
            order by sInner.date) as nextDirtyDate
    from    mySchedule sOuter
    where sOuter.dirty=0
            and sOuter.date between @startDate and @endDate
    ) sub
group by trainer, nextDirtyDate
having dateDiff(d, min(date), isNull(nextDirtyDate,dateAdd(d,1,@endDate))) >= @days

注意:我不知道性能有多好,因为它使用的是运行总数

当dirty=0时,它还会使用dirty标志来获得一个正数 e、 g.当B.脏=0时,则为1其他-1结束

它使用查询中两个位置的天数 美国日期-NNN+1作为起始日期 当B.Dirty=0时有SumCASE,那么1 ELSE-1 END=NNN


这些都是很好的答案!谢谢你抽出时间来解决这个问题。我接受了jhinkley而不是你的,因为它在我的数据集上执行得更快。再次感谢!工作起来非常漂亮,在大约一秒钟的时间内在150000条记录数据集上执行。谢谢Hee jhinkley,我正在努力让它在我自己的实现中工作。但是我没有一个肮脏的约会。你能看一下吗?