我正在安排一张时间表,办公室在早上有约会,然后在午餐时关闭,然后在下午更多约会。该办公室正在寻找能够根据已有的开始和结束时间即时更改其约会频率和数量的能力。
例如:如果办公室预约每60分钟从10 - 12午餐12-1和下午预约1-3,那么日程表将如下所示
Day Time IsBlocked EndTime
2013-07-01 10:00:00.0000000 0 NULL
2013-07-01 11:00:00.0000000 0 NULL
2013-07-01 12:00:00.0000000 1 13:00:00.0000000
2013-07-01 13:00:00.0000000 0 NULL
2013-07-01 14:00:00.0000000 0 NULL
让我们说他们希望每隔半小时(30分钟)将约会更改为 2个约会 他们可以调用存储过程
ChangeAppointmentFrequency(@day = '7/1/2013', @intervalInMinutes = 30, @numberOfAppointmentsInTheInterval = 2)
它会在新的插槽中插入新的约会,并保持任何现有的约会不变。
Day Time IsBlocked EndTime
2013-07-01 10:00:00.0000000 0 NULL
2013-07-01 10:00:00.0000000 0 NULL
2013-07-01 10:30:00.0000000 0 NULL
2013-07-01 10:30:00.0000000 0 NULL
2013-07-01 11:00:00.0000000 0 NULL
2013-07-01 11:00:00.0000000 0 NULL
2013-07-01 11:30:00.0000000 0 NULL
2013-07-01 11:30:00.0000000 0 NULL
2013-07-01 12:00:00.0000000 1 13:00:00.0000000
2013-07-01 13:00:00.0000000 0 NULL
2013-07-01 13:00:00.0000000 0 NULL
2013-07-01 13:30:00.0000000 0 NULL
2013-07-01 13:30:00.0000000 0 NULL
2013-07-01 14:00:00.0000000 0 NULL
2013-07-01 14:00:00.0000000 0 NULL
2013-07-01 14:30:00.0000000 0 NULL
2013-07-01 14:30:00.0000000 0 NULL
我很难在不使用游标的情况下雄辩地找到开始和结束日期 感谢
初始表
CREATE TABLE Schedule([Day] DATE,[Time] TIME, IsBlocked bit, EndTime TIME);
insert into Schedule ([Day], [Time], IsBlocked, EndTime) values
('7/1/2013', '10:00:00', 0, null),
('7/1/2013', '11:00:00', 0, null),
('7/1/2013', '12:00:00', 1, '13:00:00'),
('7/1/2013', '13:00:00', 0, null),
('7/1/2013', '14:00:00', 0, null)
答案 0 :(得分:1)
假设您的答案是约会不能重叠,我会像这样处理问题。
根据您对插槽持续时间的(新)定义,并根据办公室在早上打开的时间(当然,关闭)创建一个CTE,其中包含工作日中每个插槽的开始和结束时间)。
然后从该CTE插入现有约会表,其中不存在任何约会(或午餐时段),其开始时间或结束时间将介于您的CTE时段的开始时间和结束时间之间。
P.S。只有在给定/定义约会时间时,您必须计算结束时间。开始时间取决于办公室的开放时间。
答案 1 :(得分:1)
你的目标不明确,但我不确定你的设计是否有解决方案。
您的约会表中没有主键,它会立即抛出警告标志。从实际角度来看,您无法知道要配对的记录。如果并行预约开始时间相互抵消会怎样?
例如,假设一组约会从小时和半小时开始,另一组从1/4和3/4小时开始。您的模型中没有任何内容可以证明这一点。它可以很容易地被解释为每1/4小时开始的一系列15分钟约会。
如果你想要平行的不同轨道,那么你需要某种标识符来区分轨道。轨道ID可以代表会议室,主机或更抽象的东西。
我还建议在每个约会行中同时包含开始和停止时间。你为什么要假设一个约会的结束和下一个约会的开始之间没有差距?
答案 2 :(得分:0)
我能够使用CTE为AMtimes和PMTimes
完成此操作IF EXISTS (SELECT * FROM sys.procedures WHERE Name = 'InsertAppointmentDay' AND [type_desc] = 'SQL_STORED_PROCEDURE')
DROP PROCEDURE InsertAppointmentDay;
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[InsertAppointmentDay]
@BACCode char(6)
,@Division varchar(10)
,@ScheduleDate date
,@StartTime1 time(7)
,@EndTime1 time(7)
,@StartTime2 time(7)
,@EndTime2 time(7)
,@TimeZoneAbbreviation char(6)
AS
BEGIN
DECLARE @IntervalMinutes INT
DECLARE @AppointmentsPerInterval INT
DECLARE @ErrorMessage NVARCHAR(4000) ;
DECLARE @ErrorState INT ;
-- make sure the dealer does not already have records in the schedule table for that day. We want to make sure if you already have appointments for that day
if exists (select Id from Schedule where DealerDivision = @Division and DealerBACCode = @BACCode and AppointmentDay = @ScheduleDate)
begin
set @ErrorMessage = 'a record already exist in schedule table with DealerDivision = '+@Division+' and DealerBACCode = '+@BACCode+' and AppointmentDay = '+CAST(@ScheduleDate as varchar(20));
RAISERROR (@ErrorMessage, 16, @ErrorState );
Return;
end
BEGIN TRY
BEGIN TRANSACTION
DECLARE @ZipOffset char(6);
SELECT @ZipOffset = [TimeZoneOffset] FROM [TimeZone] WHERE [TimeZoneAbbreviation] = @TimeZoneAbbreviation;
-- find out from the frequency table how many minutes are in the interval and how many appointments per interval. look it up by FrequencyCode in the Frequency table
select @IntervalMinutes = IntervalMinutes, @AppointmentsPerInterval= AppointmentsPerInterval
from Frequency where Code = (select top 1 AppointmentCode from Dealer where Division = @Division and BACCode = @BACCode)
-- @Intervals table is a temp table with all the possiable timeslots we will add (a morning section and an afternoon section)
-- example. if the location is open from 10:00 to 11:00 lunch then 13:00 to 15:00 the and the interval is 60 minutes you will get
-- 10:00
-- 11:00
-- 13:00
-- 14:00
-- 15:00
DECLARE @Intervals table ( [Time] TIME UNIQUE ([Time]))
if (@StartTime2 is null)
begin
;WITH AmSlots([TimeSlot] ) AS
(
SELECT @StartTime1 UNION ALL
SELECT
[TimeSlot] = DATEADD(mi, @IntervalMinutes, [TimeSlot])
FROM AmSlots WHERE DATEADD(mi, @IntervalMinutes, [TimeSlot]) <= @EndTime1
)
insert into @Intervals select [TimeSlot] from [AmSlots]
end
else
begin
print 'pm times'
;WITH AmSlots([TimeSlot] ) AS
(
SELECT @StartTime1 UNION ALL
SELECT
[TimeSlot] = DATEADD(mi, @IntervalMinutes, [TimeSlot])
FROM AmSlots WHERE DATEADD(mi, @IntervalMinutes, [TimeSlot]) <= @EndTime1
) ,PmSlots([TimeSlot] ) AS
(
SELECT @StartTime2 UNION ALL
SELECT
[TimeSlot] = DATEADD(mi, @IntervalMinutes, [TimeSlot])
FROM PmSlots WHERE DATEADD(mi, @IntervalMinutes, [TimeSlot]) <= @EndTime2
)
insert into @Intervals select [TimeSlot] from [AmSlots] union all select [TimeSlot] from [PmSlots]
end
-- @DayAppointments is a table to store the combination of time slots with the Number of appointments per interval
-- example if the location is open from 10:00 to 11:00 lunch then 13:00 to 14:00 the and the interval = 60 minutes and the AppointmentsPerInterval = 3 you will get
-- 1 | 10:00
-- 2 | 10:00
-- 3 | 10:00
-- 1 | 11:00
-- 2 | 11:00
-- 3 | 11:00
-- 1 | 13:00
-- 2 | 13:00
-- 3 | 13:00
-- 1 | 14:00
-- 2 | 14:00
-- 3 | 14:00
DECLARE @DayAppointments TABLE
(
[AppointmentNumberForTimeSlot] INT,
[Time] TIME
UNIQUE ([AppointmentNumberForTimeSlot],[Time])
)
-- Quanity is a sequence table (if @AppointmentsPerInterval = 3 Quanity will contain 1, 2, 3) used to cross join with @Intervals to get the @DayAppointments
;WITH Quanity([AppointmentNumberForTimeSlot] ) AS
(
SELECT 1 UNION ALL
SELECT [AppointmentNumberForTimeSlot] = [AppointmentNumberForTimeSlot] + 1 FROM Quanity WHERE [AppointmentNumberForTimeSlot] < @AppointmentsPerInterval
)
insert into @DayAppointments select [AppointmentNumberForTimeSlot], [Time] from Quanity cross join @Intervals
--select * from @DayAppointments
-- insert one record into Schedule for each record in @DayAppointments
INSERT INTO [Schedule] ([DealerBACCode],[DealerDivision],[AppointmentDay],[AppointmentTime], [ZipOffset], [TimeZoneAbbreviation], [ModifiedBy])
select @BACCode , @Division ,@ScheduleDate ,[Time] , @ZipOffset , @TimeZoneAbbreviation , 'InsertAppointmentDay' from @DayAppointments where [Time] IS NOT NULL
print 'about to compelte transaction'
COMMIT TRANSACTION
END TRY
BEGIN CATCH
print 'about to Rollback transaction'
Rollback Transaction
set @ErrorMessage = ERROR_MESSAGE()
set @ErrorState = ERROR_STATE()
RAISERROR (@ErrorMessage, 16, @ErrorState);
Return;
END CATCH;
END