MSSQL日期时间重叠问题的可用性和不可用性

时间:2015-10-14 11:46:37

标签: sql sql-server sql-server-2008

在插入DateFrom,DateTo,SatrtTime,EndTime时,需要在MS-SQL中找到重叠记录。

假设我在特定的开始时间和结束时间安排FromDate到EndDate的教师讲课时间。

需要克服以下两个记录重叠的情况

╔═════════════════╦════════════════╦══════════════════╦══════════════════════╦════════════════════╗
║   DateFrom;     ║     DateTo;    ║    IsFullDay;    ║     StartTime;       ║       EndTime;     ║
║     {Date};     ║     {Date};    ║     {Bit};       ║      {Time(7)};      ║      {Time(7)};    ║
╠═════════════════╬════════════════╬══════════════════╬══════════════════════╬════════════════════╬═══════════════╣
║ 2015-10-10;     ║ 2015-10-17;    ║               0; ║     13:00;           ║      14:45;        ║ **Inserted**  ║
║ 2015-10-16;     ║ 2015-10-18;    ║               0; ║     14:00;           ║      14:15;        ║ **Overlapped**║
║ 2015-10-11;     ║ 2015-10-11;    ║               1; ║     00:00;           ║      00:00;        ║ **Overlapped**║
╚═════════════════╩════════════════╩══════════════════╩══════════════════════╩════════════════════╝═══════════════╝

请建议更改MSSQL程序。

4 个答案:

答案 0 :(得分:2)

不幸的是,MS SQL没有您需要检查的范围类型。将Start和End作为DateTime值而不是像您一样使用单独的Date和Time值是明智的。假设你将它们改为DateTime:

declare @Start DateTime = '2015/10/16 14:00';
declare @endDate DateTime = '2015/10/18 14:15';

select count(*) from myTable where @endDate > DateFrom and @Start < DateTo;

如果结果不为0则表示您有重叠。

答案 1 :(得分:1)

您可以插入具有重叠条件的选择:

INSERT MyTable (DateFrom, DateTo, IsFullDay, StartTime, EndTime)
SELECT MyDateFrom, MyDateTo, MyIsFullDay, MyStartTime, MyEndTime
FROM MyTable mt
WHERE
   NOT EXISTS (SELECT 1 FROM MyTable mt2
               WHERE (MyDateTo > mt2.DateFrom and MyDateTo <= mt2.DateTo) or
                     (mt2.DateTo > MyDateFrom and mt2.DateTo <= MyDateTo))

答案 2 :(得分:1)

(我会添加这个添加评论,但它没有让我把代码放在那里)

然后转换值以将它们作为日期时间(因为你会这么多次,我想你会想把它作为一个函数创建):

SELECT  COUNT(*)
FROM    myTable
WHERE   @endDate > CAST(CONVERT(VARCHAR(10), DateFrom, 111) + ' ' +
        CONVERT(VARCHAR(10), StartTime, 114) AS DATETIME) AND
        @Start < CAST(CONVERT(VARCHAR(10), DateTo, 111) + ' ' +
        CONVERT(VARCHAR(10), EndTime, 114) AS DATETIME);

编辑:BTW我没有在插入的上下文中提供示例,因为如果您正在进行调度应用程序,那么您需要进行各种检查。

答案 3 :(得分:0)

感谢@Cetin Basoz和@Lajos Arpad提出您的建议,我已经尝试过您建议的解决方案,但我可能会犯一些错误来实施。

BTW我的项目架构师允许我添加另一个详细信息表,其中需要每天插入一个开始结束时间,所以我的新时间表就像

主表可用性日期 ╔══════════╦════════════╦═══════════╦═══════════╦═ ════════╦═══════╗

║LectureId║DateFrom║DateTo║IsFullDay║StartTime║EndTime║

║10512║2015-10-14║2015-10-17║1║11:00║11:30║

║10513║2015-10-12║2015-10-14║0║11:00║12:30║

╚══════════╩════════════╩═══════════╩══════════ ═╩═════════╩═══════╝

此处ISFullDay表示全天可用性

详细信息表可用性时间 ╔══════════╦════════════════════╦═════════════════ ══╗

║LectureId║StartDateTime║EndDateTime║

║10512║2015-10-1400:00:00║2015-10-1423:59:59║

║10512║2015-10-1500:00:002015-10-14 23:59:59║

║10512║2015-10-1600:00:00║2015-10-1423:59:59║

║10512║2015-10-1700:00:002015-10-14 23:59:59║

║10513║2015-10-1211:00:00║2015-10-1212:30:00║

║10513║2015-10-1311:00:00║2015-10-1312:30:00║

║10513║2015-10-1411:00:00║2015-10-1412:30:00║

╚══════════╩════════════════════╩══════════════ ═════╝

程序变更如下 DECLARE @DetailDateTime TABLE(StartDate DATETIME,EndDate DATETIME) DECLARE @EndDateTable NVARCHAR(10)= @EndTime

IF(@IsFullDay = 1) 开始 SET @StartTime = '00:00' SET @ EndDateTable = '00:00' SET @EndTime = '23:59:59:900' - 当不依赖@IsFullDay时替换此值 结束 --IF(@DateFrom&lt; @DateTo) - 如果From和To Date相同,则时间表中不需要任何值取消注释 开始     ; WITH DetailDateTime作为
    (
    SELECT 1 AS COUNTER,@ DateFrom AS DateFrom,@ DateFrom AS DateTo     UNION ALL
    SELECT COUNTER + 1,DATEADD(DAY,COUNTER,@ DateFrom),DATEADD(DAY,COUNTER,@ DateFrom)
    来自DetailDateTime
    在哪里DATEADD(DAY,COUNTER,@ DateFrom)&lt; = @DateTo
    )
    INSERT INTO @DetailDateTime SELECT DateFrom + @ StartTime StartTime,DateTo + @ EndTime FROM DetailDateTime

如果(不存在(     选择TOP 1 * FROM     [dbo] .AvailabilityTime A WITH(NOLOCK)     INNER JOIN [dbo] .AvailabilityDates D WITH(NOLOCK)ON A.LectureId = D.LectureId AND ISNULL(D.ISDELETED,0)= 0     INNER JOIN @DetailDateTime B ON(A.StartTime&lt; B.EndDate)AND(B.StartDate&lt; A.EndTime)AND A.AvailabiliyId&lt;&gt; @AvailabiliyId     )) 开始     IF(@AvailabiliyId = 0)     开始         INSERT INTO [dbo] .AvailabilityDate ...     结束     其他     BEGIN
        更新[dbo] .AvailabilityDate ... WHERE A.AvailabiliyId = @AvailabiliyId         DELETE FROM [dbo] .AvailabilityTime WHERE NonAvailabiliyId = @NonAvailabiliyId     结束     INSERT INTO [dbo] .AvailabilityTime SELECT @ NonAvailabiliyId,* FROM @DetailDateTime 结束 其他     开始         SET @AvailabiliyId = -1 - 重叠冲突     END

非常感谢我花时间陪伴我。 :)

如果在这个解决方案中,请告诉我,我会卡在其他地方