/ / Jak wykryć nakładanie się między dwoma datetime w SQL? - sql, sql-server, sql-server-2008, sql-server-2008-R2

Jak wykrywać nakładanie się dwóch datetime w SQL? - sql, sql-server, sql-server-2008, sql-server-2008-r2

Mam tabelę jak poniżej:

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

Pracownik 1030 dodał swoje wysiłki na 01.12.2016 dla zakresów czasowych 07:30 do 12:30 i 13:30 do 16:30.

Po tym nie powinien podejmować wysiłku w tych przedziałach czasowych. Może wprowadzić wysiłek przed 07:30 lub 12:30 do 13:30 lub później niż 16:30 dla 01.12.2016 lub może wejść na inny dzień.

Aby to osiągnąć, piszę poniższe zapytanie, ale zawsze zgłasza błąd i nie pozwala użytkownikom na wstawianie danych. Proszę pomóż.

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

Odpowiedzi:

2 dla odpowiedzi № 1

Przekonałem się, że te wyrażenia mogą byćuproszczone - jeśli ma zostać wykryte nakładanie się, czas musi upłynąć przed końcem istniejącej zmiany, z którą porównujesz - w takim przypadku pracownik musi również przepracować po rozpoczęciu istniejącej zmiany - więc może sprowadzać się do dwóch kluczowych warunków

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 dla odpowiedzi № 2

Wygląda na problem z braketingiem - nie jesteś ANDw obu częściach OR z EmpId = @EmpId. Wygląda również na to, że logika jest nieco wadliwa (to sprawdzasz @DateTimeOut jest późniejszy niż DateTimeOut i wcześniej niż DateTimeIn, co jeśli DateTimeOut > DateTimeIn jak się spodziewaliśmy, nigdy nie będzie zadowolony).

Próbować:

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 dla odpowiedzi nr 3

To zapytanie zapyta we wszystkich warunkach i będzie działać w twojej sprawie.

UWAGA: Odpowiedź @ 3N1GM4 jest niższy ode mnie i również działa w twojej sprawie.

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