预约可用时间

时间:2014-01-17 13:02:15

标签: sql-server stored-procedures

我想从tblAppointments表中获取给定日期和持续时间的可用时间列表

tblAppointments

id int
BookingDate datetime
BookedStartTime datetime
BookedEndTime datetime

表格中的示例数据

id  BookingDate         BookedStartTime     BookedEndTime
1   2014-02-03 00:00:00 2014-02-03 08:30:00 2014-02-03 09:00:00
2   2014-02-03 00:00:00 2014-02-03 09:00:00 2014-02-03 10:30:00
3   2014-02-03 00:00:00 2014-02-03 12:00:00 2014-02-03 14:30:00
4   2014-02-03 00:00:00 2014-02-03 15:00:00 2014-02-03 16:30:00

如果我将输入参数设为

BookingDate  : 2014-02-03    
DurationCode : 1 (eg 30 minutes)

我想得到如下结果

2014-02-03 08:00:00     2014-02-03 08:30:00
2014-02-03 10:30:00     2014-02-03 11:00:00
2014-02-03 11:00:00     2014-02-03 11:30:00
2014-02-03 11:30:00     2014-02-03 12:00:00
2014-02-03 14:30:00     2014-02-03 15:00:00
2014-02-03 16:30:00     2014-02-03 17:00:00

如果输入参数是

BookingDate  : 2014-02-03    
DurationCode : 2 (eg 15 minutes)

结果应如下所示

2014-02-03 08:00:00     2014-02-03 08:15:00
2014-02-03 08:15:00     2014-02-03 08:30:00
2014-02-03 10:30:00     2014-02-03 10:45:00
2014-02-03 10:45:00     2014-02-03 11:00:00
2014-02-03 11:00:00     2014-02-03 11:15:00
2014-02-03 11:15:00     2014-02-03 11:30:00
2014-02-03 11:30:00     2014-02-03 11:45:00
2014-02-03 11:45:00     2014-02-03 12:00:00
2014-02-03 14:30:00     2014-02-03 14:45:00
2014-02-03 14:45:00     2014-02-03 15:00:00
2014-02-03 16:30:00     2014-02-03 16:45:00
2014-02-03 16:45:00     2014-02-03 17:00:00

开始和结束预约时间为08:00和18:00

我已经编写了相同的存储过程,这似乎有效,但我想知道是否有任何简单的方法来做同样的事情。

存储过程

ALTER Procedure [dbo].[FindAvailableTime] (
  @BookingDate datetime,
  @DurationCode int
)
as
Declare @Duration datetime
Declare @DurationMinutes int
Declare @DurationHours int

select @Duration = Duration from DurationCode where DurationCodeID = @DurationCode

Set @DurationMinutes = datepart(minute,@Duration)
Set @DurationHours = datepart(hour,@Duration)
if (@DurationHours > 0) 
Begin
 Set @DurationMinutes = @DurationMinutes + (@DurationHours * 60)
End

Declare @StartTimeHR int
Declare @StartTimeMN int
Declare @EndTimeHR int
Declare @EndTimeMN int

Declare @CurrentDateTimeStart datetime
Declare @CurrentDateTimeStartString varchar(100)
Declare @CurrentDateTimeEnd datetime
Declare @CurrentDateTimeEndString varchar(100)
Declare @CurrentDateTimeEndWork datetime
Declare @CurrentDateTimeEndStringWork varchar(100)


Declare @CurrentYear int
Declare @CurrentMonth int
Declare @CurrentDay int

Set @CurrentYear = datepart(year,@BookingDate)
Set @CurrentMonth = datepart(month,@BookingDate)
Set @CurrentDay = datepart(day,@BookingDate)

Set @StartTimeHR = 8
Set @StartTimeMN = 0
Set @EndTimeHR = 18
Set @EndTimeMN = 1
Set @CurrentDateTimeStartString = convert(varchar(10),@CurrentYear) + '-' + convert(varchar(10),@CurrentMonth) + '-' + convert(varchar(10),@CurrentDay) + ' ' + convert(varchar(10),@StartTimeHR) + ':' + convert(varchar(10),@StartTimeMN) + ':' + '0'
Set @CurrentDateTimeEndString = convert(varchar(10),@CurrentYear) + '-' + convert(varchar(10),@CurrentMonth) + '-' + convert(varchar(10),@CurrentDay) + ' ' + convert(varchar(10),@EndTimeHR) + ':' + convert(varchar(10),@EndTimeMN) + ':' + '0'
set @CurrentDateTimeStart = convert(datetime, @CurrentDateTimeStartString)
set @CurrentDateTimeEnd = convert(datetime, @CurrentDateTimeEndString)

Declare @CurrentDateTimeEndTemp datetime
set @CurrentDateTimeEndTemp = dateadd(mi,@DurationMinutes,@CurrentDateTimeStart)

Declare @AppointmentStartTime datetime
Declare @AppointmentEndTime datetime

Declare @StartDate datetime
Declare @EndDate datetime
Declare @EndDateTemp datetime

Declare @StartDatePlusOne datetime
Declare @EndDateMinusOne datetime

set @StartDate = @CurrentDateTimeStart
set @EndDate = @CurrentDateTimeEnd
set @EndDateTemp = dateadd(mi,@DurationMinutes,@StartDate)

Set @StartDatePlusOne = dateadd(mi,1,@StartDate)
Set @EndDateMinusOne = DateAdd(mi,-1,@EndDateTemp)

Create Table #Appointment_AvailableTime (StartTime datetime, EndTime datetime)

if Exists (select * from tblAppointments where BookingDate = @BookingDate)
Begin
while (@EndDateTemp < @EndDate) 
Begin
    if not exists (Select * from tblAppointments where @StartDatePlusOne between BookedStartTime and BookedEndTime or @EndDateMinusOne between BookedStartTime and BookedEndTime)
    begin
         if not exists (Select * from tblAppointments where BookedStartTime Between @StartDatePlusOne and @EndDateMinusOne or BookedEndTime between @StartDatePlusOne and @EndDateMinusOne)
          Begin
           insert into #Appointment_AvailableTime values(@StartDate, @EndDateTemp)
           set @StartDate = dateadd(mi,@DurationMinutes,@StartDate)
          End
         Else
          Begin
           Select @StartDate = max(BookedEndTime) from tblAppointments where BookedStartTime Between @StartDatePlusOne and @EndDateMinusOne or BookedEndTime between @StartDatePlusOne and @EndDateMinusOne
          End

          set @EndDateTemp = dateadd(mi,@DurationMinutes,@StartDate)
          Set @StartDatePlusOne = dateadd(mi,1,@StartDate)
          Set @EndDateMinusOne = DateAdd(mi,-1,@EndDateTemp)
    End
    Else
    Begin
         Select @StartDate = max(BookedEndTime) from tblAppointments where @StartDatePlusOne between BookedStartTime and BookedEndTime or @EndDateMinusOne between BookedStartTime and BookedEndTime
         set @EndDateTemp = dateadd(mi,@DurationMinutes,@StartDate)
         Set @StartDatePlusOne = dateadd(mi,1,@StartDate)
         Set @EndDateMinusOne = DateAdd(mi,-1,@EndDateTemp)
    End
End
End
Else
Begin
Set @CurrentDateTimeEndWork = dateadd(mi,@DurationMinutes,@CurrentDateTimeStart)  
while (@CurrentDateTimeStart < @CurrentDateTimeEnd and @CurrentDateTimeEndWork < @CurrentDateTimeEnd)
Begin
    insert into #Appointment_AvailableTime values(@CurrentDateTimeStart, @CurrentDateTimeEndWork)
    set @CurrentDateTimeStart = dateadd(mi,@DurationMinutes,@CurrentDateTimeStart)
    Set @CurrentDateTimeEndWork = dateadd(mi,@DurationMinutes,@CurrentDateTimeStart)
End
End
select StartTime, EndTime from #Appointment_AvailableTime

由于

1 个答案:

答案 0 :(得分:0)

维护一个包含所有有效约会时间的表。在10小时内放置所有可能的1小时,30米,15米的插槽仍然很小(70行)。这使得添加更复杂的规则,例如“下午4点之后没有1小时约会”真的很容易。在查找表中添加星期几列可以让您轻松添加诸如“周三延长时间”或“半天周六”等内容。

CREATE TABLE tblAppointmentSlots (
  DurationID    int,
  SlotStartTime datetime CHECK (CAST(SlotStartTime AS int) = 0),
  SlotEndTime   datetime CHECK (CAST(SlotEndTime   AS int) = 0)
)
GO

INSERT tblAppointmentSlots VALUES
(1, '08:00', '08:30'),
(1, '08:30', '09:00'),
etc..
GO

ALTER Procedure [dbo].[FindAvailableTime] (
  @BookingDate datetime,
  @DurationCode int
)
AS
SELECT
  @BookingDate + SlotStartTime,
  @BookingDate + SlotEndTime
FROM tblAppointmentSlots
WHERE DurationID = @DurationCode
  AND NOT EXISTS (
    SELECT 1
    FROM tblAppointments
    WHERE @BookingDate + SlotStartTime < BookedEndTime
      AND @BookingDate + SlotEndTime   > BookedStartTime
)