2014-02-22 172 views
3

我的日程记录列表SQL筛选日期范围查询

StaffSchedules

enter image description here

他们中有些人已经订好。

BookedSchedules

enter image description here

也有一些假期

假期

enter image description here

我想只有服务人员小号chedules

Expected Schedules= StaffSchedule - BookedSchedule-Holidays

即,我只想要从StaffSchedule表

下一列2,6是我试过的查询,但它表明没有结果

with NonBookingSlots as 
(
select StartdateTime,EndDateTime from Holidays 
union all 
select StartdateTime,EndDateTime from BookedSchedules 
) 

SELECT 
    StaffId, StartdateTime, EndDateTime 
FROM StaffSchedule 
WHERE 
not exists (select 1 
       from NonBookingSlots h 
       where cast(StartdateTime as DATETIME) between 
       cast(h.startdatetime as DATETIME) 
       and cast(h.enddatetime as DATETIME) 
      ) 

SQL FIDDLE DEMO

+2

+1为一个完整的问题 – Kermit

+1

能否在工作人员的安排被部分预订或者只客满(如与您的所有示例数据的情况下)? –

+0

@ShWiVeL,其全套 – Billa

回答

1
select * 
    from dbo.StaffSchedule x 
where not exists (select 'y' 
      from dbo.BookedSchedules y 
     where y.staffid = x.staffid 
      and y.startdatetime = x.startdatetime 
      and y.enddatetime = x.enddatetime) 
    and not exists (select 'z' 
      from dbo.Holidays z 
     where cast(z.startdatetime as date) = 
       cast(x.startdatetime as date)) 

SQL小提琴在这里:http://sqlfiddle.com/#!3/07698/19/0

编辑 - 对付,范围超过一天的假期:

select * 
    from dbo.StaffSchedule x 
where not exists (select 'y' 
      from dbo.BookedSchedules y 
     where y.staffid = x.staffid 
      and y.startdatetime = x.startdatetime 
      and y.enddatetime = x.enddatetime) 
    and not exists (select 'z' 
      from dbo.Holidays z 
     where cast(z.startdatetime as date) <= 
       cast(x.startdatetime as date) 
      and cast(z.enddatetime as date) >= 
       cast(x.enddatetime as date)) 
+0

假期可以是范围。例如3月5日 - 7月3日 – Billa

+0

@Billa为持续2天以上的节假日添加了逻辑 –

3

对于我所做的假定所有的例子,在BookedSchedules的开始和结束时间会精确地匹配与StaffSchedules开始和结束倍。

随着CTE,类似这样的问题:

我不推荐使用此查询,但它可能是有帮助的,因为它是类似问题的查询。它不太可读。

with NonBookingSlots as 
(
    select null as StaffId,StartdateTime,EndDateTime from Holidays 
    union all 
    select StaffId,StartdateTime,EndDateTime from BookedSchedules 
) 

select 
    StaffId, StartdateTime, EndDateTime 
from 
    StaffSchedule 
where 
    not exists(
    select 
     1 
    from 
     NonBookingSlots 
    where 
     StaffSchedule.StaffId = isnull(NonBookingSlots.StaffId,StaffSchedule.StaffId) 
     and (
     (
      StaffSchedule.StartDateTime = NonBookingSlots.StartDateTime 
      and StaffSchedule.EndDateTime = NonBookingSlots.EndDateTime 
     ) or (
      StaffSchedule.StartDateTime < NonBookingSlots.EndDateTime 
      and StaffSchedule.EndDateTime > NonBookingSlots.StartDateTime 
     ) 
    ) 
) 

SQL小提琴:http://sqlfiddle.com/#!3/9cbf4/14

没有CTE:

这个版本是在我看来,更具有可读性。

select 
    StaffId, StartdateTime, EndDateTime 
from 
    StaffSchedule 
where 
    not exists(
    select 
     1 
    from 
     BookedSchedules 
    where 
     StaffSchedule.StaffId = BookedSchedules.StaffId 
     and StaffSchedule.StartDateTime = BookedSchedules.StartDateTime 
     and StaffSchedule.EndDateTime = BookedSchedules.EndDateTime 
) and not exists(
    select 
     1 
    from 
     Holidays 
    where 
     StaffSchedule.StartDateTime < Holidays.EndDateTime 
     and StaffSchedule.EndDateTime > Holidays.StartDateTime 
) 

SQL小提琴:http://sqlfiddle.com/#!3/9cbf4/15

随着外键 - 我建议:

如果BookedSchedules总是匹配StaffSchedule你应该使用外键StaffSchedule,而不是复制的开始并在BookedSchedules结束时间。这会产生更清晰和更高效的查询。

select 
    StaffId, StartdateTime, EndDateTime 
from 
    StaffSchedule 
where 
    not exists(
    select 
     1 
    from 
     BookedSchedules 
    where 
     StaffSchedule.Id = BookedSchedules.StaffScheduleId 
) and not exists(
    select 
     1 
    from 
     Holidays 
    where 
     StaffSchedule.StartDateTime <= Holidays.EndDateTime 
     and StaffSchedule.EndDateTime >= Holidays.StartDateTime 
) 

SQL小提琴:http://sqlfiddle.com/#!3/8a684/3

+0

我们可以在单独的地方制作它,就像我尝试过CTE一样? – Billa

+0

是的,让我更新答案 –

+0

@Billa你是说你只想要一个EXISTS子查询? –