如何检测SQ​​L中两个日期时间之间的重叠?

时间:2016-12-21 09:31:34

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

我有一张如下表:

EmpId   DateTimeIn                  DateTimeOut                 Effort
1030    2016-12-01 07:30:00.000     2016-12-01 12:30:00.000     1030
1030    2016-12-01 13:30:00.000     2016-12-01 16:30:00.000     1531

员工1030在2016-12-01的时间范围07:30至12:30和13:30至16:30插入了他的努力。

在此之后,他不应该在这些时间范围内努力。他可以在2016-12-01之前的07:30或12:30至13:30或16:30之间进行努力,或者可以在任何其他日期进入。

为了达到这个目的,我编写了一个下面的查询,但总是抛出错误并且不允许用户插入数据。请帮忙。

IF EXISTS (SELECT 1 FROM TimesheetEntries 
WHERE EmpId = @EmpId AND (@DateTimeIn >= DateTimeIn AND @DateTimeIn < DateTimeOut)  
OR (@DateTimeOut >= DateTimeOut AND @DateTimeOut < DateTimeIn))
BEGIN
    RAISERROR ('You already input your effort for the given time range.',16,1)
    RETURN 
END

3 个答案:

答案 0 :(得分:3)

看起来像是一个包围问题 - 您AND OREmpId = @EmpId @DateTimeOut DateTimeOut DateTimeIn。看起来逻辑稍微有点错误(您检查DateTimeOut > DateTimeIn是否早于IF EXISTS ( SELECT 1 FROM TimesheetEntries WHERE EmpId = @EmpId AND ((@DateTimeIn >= DateTimeIn AND @DateTimeIn <= DateTimeOut) OR (@DateTimeOut >= DateTimeIn AND @DateTimeOut <= DateTimeOut)) ) BEGIN RAISERROR ('You already input your effort for the given time range.',16,1) RETURN END 且早于let appVersion = Bundle.main.infoDictionary!["CFBundleShortVersionString"]! let buildNum = Bundle.main.infoDictionary!["CFBundleVersion"]! let versionInfo = "\(appVersion) (build \(buildNum))" // versionInfo is now something like "2.3.0 (build 17)" ,如果as! String正如我们所期望的那样,那么从不满意)。

尝试:

appVersion

答案 1 :(得分:2)

我曾经发现这些表达式可以简化 - 如果要检测重叠,那么时间必须在你正在比较的现有班次结束之前 - 如果是这样,那么工人也必须在现有轮班开始后工作 - 所以它可以归结为两个关键条件

IF EXISTS (SELECT 1 FROM TimesheetEntries 
WHERE EmpId = @EmpId AND @DateTimeIn  < DateTimeOut  
AND @DateTimeOut > DateTimeIn)   --has to have started before end AND  ended after the start
BEGIN
RAISERROR ('You already input your effort for the given time range.',16,1)
RETURN 
END

答案 2 :(得分:1)

此查询将查询所有条件并适用于您的案例。

注意:@3N1GM4's answer比我短,也适用于你的情况。

IF EXISTS 
(
    select TOP 1 1 from HR.TimesheetEntries where SubmittedByEmpId = 1030 AND 
(
(DateTimeIn > @DateTimeIn AND DateTimeIn < @DateTimeIn) OR (DateTimeOut > @DateTimeOut AND DateTimeOut < @DateTimeOut) OR
(DateTimeIn > @DateTimeIn AND DateTimeOut < @DateTimeIn) OR (DateTimeOut > @DateTimeOut AND DateTimeIn < @DateTimeOut) OR
(DateTimeOut > @DateTimeIn AND DateTimeIn < @DateTimeIn) OR (DateTimeIn > @DateTimeOut AND DateTimeOut < @DateTimeOut) OR
(DateTimeOut > @DateTimeIn AND DateTimeOut < @DateTimeIn) OR (DateTimeOut > @DateTimeOut AND DateTimeOut < @DateTimeOut)
)
)
BEGIN
    RAISERROR ('You already input your effort for the given time range.',16,1)
    RETURN 
END