2014-02-22 170 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子查詢? –