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 № 1Przekonał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ś AND
w 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