/ / ¿Cómo detectar la superposición entre dos datetime en SQL? - sql, sql-server, sql-server-2008, sql-server-2008-r2

¿Cómo detectar la superposición entre dos fechas en SQL? - sql, sql-server, sql-server-2008, sql-server-2008-r2

Tengo una tabla como la siguiente:

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

El empleado 1030 ha insertado su esfuerzo el 2016-12-01 para los rangos de tiempo de 07:30 a 12:30 y de 13:30 a 16:30.

Después de esto, no debe ingresar su esfuerzo en estos rangos de tiempo. Puede ingresar esfuerzo antes de las 7:30 o de 12:30 a 13:30 o después de las 16:30 del 2016-12-01 o puede ingresar cualquier otro día.

Para lograr esto, escribo una consulta a continuación, pero siempre está generando errores y no permite a los usuarios insertar datos. Por favor ayuda.

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

Respuestas

2 para la respuesta № 1

Una vez encontré que estas expresiones pueden sersimplificado: si se va a detectar una superposición, el tiempo debe transcurrir antes del final de un turno existente con el que se está comparando. Si ese es el caso, entonces el trabajador también debe haber trabajado después del inicio del turno existente. Puede reducirse a dos condiciones clave

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

3 para la respuesta № 2

Parece un problema de paréntesis, no estás ANDambas partes de tu OR con el EmpId = @EmpId. También parece que la lógica es ligeramente defectuosa (verifica que @DateTimeOut es más tarde que DateTimeOut y antes de DateTimeIn, que si DateTimeOut > DateTimeIn como esperábamos, nunca estaremos satisfechos).

Tratar:

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

1 para la respuesta № 3

Esta consulta informará en todas las condiciones y funcionará para su caso.

NOTA: @ 3N1GM4 "s respuesta Es más corto que yo y también funciona para tu caso.

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