我有一份日程记录列表
StaffSchedules
其中一些人已经预订了。
BookedSchedules
还有一些假期
假日
我想只获得可用的员工时间表
Expected Schedules= StaffSchedule - BookedSchedule-Holidays
即,我只想从StaffSchedule Table
获取第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)
)
答案 0 :(得分: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
)
答案 1 :(得分: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))