2011-12-26 53 views
4

我有了下面列的事件表:SQL服務器的日期/時間重疊檢查事件調度

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點到下午6點或從上午11:00到下午4:00,但不是上午11:00到下午5:00或下午4:30到5:00下午。

我該如何檢查?我知道這不是這張表的最佳設計,但我必須堅持這個設計,否則我們將不得不改變很多中間層和客戶端代碼。

回答

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(*)> 0,約好存在。如果沒有,現場是免費的

+0

您還需要測試完整覆蓋範圍 – 2011-12-26 19:50:20

+0

謝謝各位!非常感激。 :) – user1100221 2011-12-26 22:21:06

3

添加新記錄或修改現有記錄時,應檢查您的開始或結束時間戳是否落入已存在的時間範圍內,並且新範圍未覆蓋現有時間範圍。

假設日期也很重要,不僅僅是時間,還有更好的方式來存儲開始和結束日期和時間作爲DATETIME列,例如StartDT和EndDT - 在這種情況下,您必須使用此語句檢查非重疊的其他行

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子句而不是非你可以重寫它存在

所以,如果你無法改變的模式,您只需簡單地改變StartDT和EndDT到表情,從構成對應的值底層字符串列,例如

StartDT = SUBSTRING(StartDate, 1, 10) + ' '+ StartTime 
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