SQL Server日期/时间重叠检查事件调度

时间:2011-12-26 19:18:25

标签: sql sql-server-2008

我有一个包含以下列的事件表:

StartDate datetime
EndDate datetime
StartTime nvarchar(10)
EndTime nvarchar(10)

假设记录在表格中有这些值:

StartDate: 2011-12-22 00:00:00.000
EndDate: 2011-12-22 00:00:00.000
StartTime: 4:00 PM
EndTime: 5:00 PM

现在,如果有人来安排活动,我需要确保他不能在同一时间或在现有活动的开始和结束时间之间安排活动。

因此,他可以安排从下午5:00到下午6:00或上午11:00到下午4:00但不是上午11:00到下午5:00或下午4:30到下午5:00

我该如何检查?我知道这不是这个表的最佳设计,但我必须坚持这个设计,否则我们将不得不改变很多中间层和客户端代码。

3 个答案:

答案 0 :(得分:3)

添加新记录或修改现有记录时,您应检查您的开始或结束时间戳是否不在现有时间范围内,新范围不会覆盖现有时间范围。

假设日期也很重要,不仅是时间,那么更好的方式将开始和结束日期和时间存储为DATETIME列,例如StartDT和EndDT - 在这种情况下,您必须使用此语句检查非重叠的其他行< / p>

Where not exists(
    select * from yourtable 
    where (@newstart >= StartDT AND @newstart < EndDT) 
    OR (@newend > StartDT AND @newend <= EndDT) 
    OR (@newstart <= StartDT AND @newend >= EndDT)
)

当然,您可以将其重写为EXISTS子句而不是NON EXISTS

因此,如果您无法更改架构,则只需将StartDT和EndDT更改为表达式,这些表达式组成基础字符串列中的相应值,例如

 StartDT = SUBSTRING(StartDate, 1, 10) + ' '+ StartTime

答案 1 :(得分:0)

试试这个

declare @apptDate DATETIME

SET @apptDate = '12/22/2011 4:30PM'
select COUNT(*) 
from t1
where @apptDate Between
CAST( StartDate+StartTime as DateTime) and CAST( EndDate+EndTime as DateTime)  

SET @apptDate = '12/22/2011 6:30PM'
select COUNT(*) 
from t1
where @apptDate Between
CAST( StartDate+StartTime as DateTime) and CAST( EndDate+EndTime as DateTime)  

如果count(*)&gt; 0,预约存在。如果没有,该地点是免费的

答案 2 :(得分:0)

想在这里发布我的查询 - 可能对某人有帮助。奇迹般有效。谢谢你的帮助!

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[PS_Event_Insert]
(
@UserID int,
@AmenityID int,
@DateFrom datetime,
@DateTo datetime,
@TimeFrom nvarchar(50),
@TimeTo nvarchar(50),
@Description nvarchar(max),
@IsPrivate bit,
@NumberOfPeople nvarchar(100),
@Food bit,
@StatusID int,
@Notes nvarchar(500) = NULL,
@EventID int OUTPUT
)
AS
declare @newdtfrom datetime = cast(@DateFrom + ' ' + @TimeFrom as datetime)
declare @newdtto datetime = cast(@DateTo + ' ' + @TimeTo as datetime)

DECLARE @RecCount int

BEGIN

SET @RecCount = (
select count(*) from [events]   
where (@newdtfrom >= cast([datefrom] + ' ' + [timefrom] as datetime) and @newdtfrom   <= cast([dateto] + ' ' + [timeto] as datetime))
or (@newdtto > cast([datefrom] + ' ' + [timefrom] as datetime) and @newdtto <=   cast([dateto] + ' ' + [timeto] as datetime))
or (@newdtfrom <= cast([datefrom] + ' ' + [timefrom] as datetime) and @newdtto >= cast([dateto] + ' ' + [timeto] as datetime))  
AND
[AmenityID] = @AmenityID
AND 
[StatusID] = 5
)

IF (@RecCount = 0)
BEGIN
    INSERT INTO [Events]
    (
        [UserID],
        [AmenityID],
        [DateFrom],
        [DateTo],
        [TimeFrom],
        [TimeTo],   
        [Description],
        [IsPrivate],
        [NumberOfPeople],
        [Food],
        [StatusID],
        [Notes]
    )
    VALUES
    (
        @UserID,
        @AmenityID,
        @DateFrom,
        @DateTo,
        @TimeFrom,
        @TimeTo,
        @Description,
        @IsPrivate,
        @NumberOfPeople,
        @Food,
        @StatusID,
        @Notes
    )

SET @EventID = SCOPE_IDENTITY()
END
ELSE
BEGIN
    SET @EventID = -999
END
END