Как получить время выезда для сотрудника, работающего в ночную смену - PullRequest
0 голосов
/ 02 октября 2019

У меня есть таблица для хранения посещаемости сотрудников, проверить и проверить соответственно. Большинство людей работают в дневную смену, а большинство работают на ночь. Для тех, кто работает в дневное время, он хорошо рассчитывает и показывает данные, но для тех, кто работает всю ночь, я могу получить точную посещаемость для них. Вот структура и пример данных

CREATE TABLE Shifts
(
ID INT PRIMARY KEY,
ShiftName VARCHAR(25),
StartTime TIME,
EndTime TIME,
IsNightShift bit
)

INSERT INTO Shifts VALUES (1, 'Day Shift', '09:00:00', '18:00', 0);
INSERT INTO Shifts VALUES (2, 'Night Shift', '21:00:00', '05:00', 1);


CREATE TABLE Attendance
(
ID INT,
EmpCode INT,
ShiftCode INT, 
CheckIn DATETIME,
CheckOut DATETIME,
CONSTRAINT FK_PersonOrder FOREIGN KEY (ShiftCode)
REFERENCES Shifts(ID)
)



INSERT INTO Attendance VALUES (1, 12, 1, '2019-09-01 09:16:23', NULL)
INSERT INTO Attendance VALUES (2, 12, 1, NULL, '2019-09-01 18:01:56')
INSERT INTO Attendance VALUES (3, 07, 2, '2019-09-01 21:00:00', NULL)
INSERT INTO Attendance VALUES (4, 07, 2, NULL, '2019-09-02 08:48:21')
INSERT INTO Attendance VALUES (5, 12, 1, '2019-09-02 09:27:00', NULL)
INSERT INTO Attendance VALUES (6, 12, 1, NULL, '2019-09-02 18:45:00')
INSERT INTO Attendance VALUES (7, 07, 2, '2019-09-02 21:19:17', NULL)
INSERT INTO Attendance VALUES (8, 07, 2, NULL, '2019-09-02 23:30:56')
INSERT INTO Attendance VALUES (9, 07, 2, '2019-09-03 00:23:00', NULL)
INSERT INTO Attendance VALUES (10, 07, 2, NULL, '2019-09-03 07:19:00')

Я хочу узнать, сколько раз в день сотрудник регистрировался или проверялся, а также для сотрудника 07, когда я собираюсь получить посещаемость для'2019-09-02' это должно показать следующий набор результатов. Это означает, что сотрудник сначала зарегистрировался в 9:19 вечера по номеру 2019-09-02, затем ушел на некоторое время в 23:30, затем снова вернулся в 12:23 AM, а затем ушел утром в 07:19 AM. Поскольку время его смены составляет от 09:00 PM до 05:00 AM, поэтому он может работать в течение ночи, а посещаемость будет учитываться как 2019-09-02

EmpCode   CheckIn               
07        2019-09-02 21:19:17
07        2019-09-03 00:23:00

EmpCode   CheckOut               
07        2019-09-02 23:30:56
07        2019-09-03 07:19:00

Я использую эти запросы для получения набора результатов.

DECLARE @givenDate DATE = '2019-09-02';
DECLARE @EmpCode INT = 07;
SELECT ROW_NUMBER() OVER(ORDER BY CheckIn) AS RowNum, EmpCode, CheckIn
FROM Attendance, Shifts
WHERE Attendance.ShiftCode = Shifts.ID AND
CAST(CheckIn AS DATE) = CAST(@givenDate AS DATE) AND EmpCode=@EmpCode
AND CheckIn IS NOT NULL;

SELECT ROW_NUMBER() OVER(ORDER BY CheckOut) As RowNum, EmpCode, CheckOut
FROM Attendance, Shifts
WHERE Attendance.ShiftCode = Shifts.ID AND
CAST(CheckOut AS DATE) = 
CASE WHEN IsNightShift = 1 THEN DATEADD(DAY, 1, CAST(@givenDate AS DATE)) ELSE CAST(@givenDate AS DATE) END
AND EmpCode=@EmpCode

Обратите внимание, что я не использую тайминги Shift в своем запросе, может быть, кто-то может помочь мне, как я могу сделать это удобным, и это может помочь мне получить желаемый набор результатов.

Ответы [ 2 ]

2 голосов
/ 02 октября 2019

Я опубликую свой ответ от ОП (удален), дубликат здесь в любом случае:

DECLARE @date date = '20190902';

WITH CheckInOut AS(
    SELECT A.ID,
           A.EmpCode,
           A.ShiftCode,
           A.CheckIn,
           LEAD(A.CheckOut) OVER (PARTITION BY A.EmpCode ORDER BY COALESCE(A.CheckIn,A.CheckOut)) AS CheckOut
    FROM dbo.Attendance A)
SELECT S.ShiftName,
       ST.ShiftStart,
       ST.ShiftEnd,
       CIO.CheckIn,
       CIO.CheckOut
FROM dbo.Shifts S
     CROSS APPLY (VALUES(DATEADD(MINUTE,DATEDIFF(MINUTE,'00:00:00',S.StartTime), CONVERT(datetime2(0),@date)),
                         DATEADD(DAY, CASE WHEN S.EndTime < S.StartTime THEN 1 ELSE 0 END,DATEADD(MINUTE,DATEDIFF(MINUTE,'00:00:00',S.EndTime), CONVERT(datetime2(0),@date))))) ST(ShiftStart,ShiftEnd)
     JOIN CheckInOut CIO ON CIO.CheckIn >= ST.ShiftStart 
                        AND CIO.CheckIn < ST.ShiftEnd;
0 голосов
/ 02 октября 2019

Попробуйте, ваша таблица смены заканчивает ночную смену в 5:00, а последняя проверка для Emp 07 - после 7:00. Но попробуйте:

DECLARE @nEmpID INT = 7
DECLARE @givenDate DATE = '2019-09-02';

;WITH CTE as (
    SELECT  DATEADD(hour,DATEDIFF(hour,'00:00:00',StartTime),CAST(@givenDate as datetime)) ShiftStart
            ,DATEADD(hour,DATEDIFF(hour,'00:00:00',EndTime),DATEADD(day, CASE WHEN IsNightShift = 1 THEN 1 ELSE 0 END,CAST(@givenDate as datetime))) ShiftEnd
            ,ID
            , ShiftName
FROM #Shifts
)

select EmpCode,ShiftName,CheckIn,CheckOut 
from #Attendance t1
INNER JOIN CTE t2 on t1.ShiftCode = t2.ID
WHERE t1.EmpCode = @nEmpID and 
        ((t1.CheckIn >= t2.ShiftStart and t1.CheckIN <= t2.ShiftEnd)
            OR (t1.CheckOut >= t2.ShiftStart and t1.CheckOut <= t2.ShiftEnd))

РЕДАКТИРОВАТЬ: Если вам нужно учитывать сверхурочные, то это изменение также будет обрабатывать:

DECLARE @nEmpID INT = 7
DECLARE @givenDate DATE = '2019-09-02';

;WITH CTE as (
    SELECT  DATEADD(hour,DATEDIFF(hour,'00:00:00',StartTime),CAST(@givenDate as datetime)) ShiftStart
            ,DATEADD(hour,DATEDIFF(hour,'00:00:00',EndTime),DATEADD(day, CASE WHEN IsNightShift = 1 THEN 1 ELSE 0 END,CAST(@givenDate as datetime))) ShiftEnd
            , DATEADD(hour,DATEDIFF(hour,'00:00:00',StartTime),CAST(DATEADD(day,1,@givenDate) as datetime)) NextShiftStart
            ,ID
            , ShiftName
FROM #Shifts
)

select EmpCode,ShiftName,CheckIn,CheckOut 
from #Attendance t1
INNER JOIN CTE t2 on t1.ShiftCode = t2.ID
WHERE t1.EmpCode = @nEmpID and 
        ((t1.CheckIn >= t2.ShiftStart and t1.CheckIN <= t2.ShiftEnd)
            OR (t1.CheckOut >= t2.ShiftStart and t1.CheckOut <= t2.NextShiftStart))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...