夜班员工的先进和后出时间

ebe*_*zer 4 sql-server sql-server-2012

我可以使用 min 和 max来让FirstIn - LastOut离开白班员工

select 
    UserId,
    [date], 
    min(convert(char(5), [Login], 108)) as FirstIN,
    max(convert(char(5), LogOut,108)) as LastOUT
from Employee
group by UserId, [date]
Run Code Online (Sandbox Code Playgroud)

但我不能为夜班员工做,比如下午 5:30 到第二天早上 2:30。同一天(第二天)他们将在下午 5:30 再次到来。

轮班表

select 
    UserId,
    [date], 
    min(convert(char(5), [Login], 108)) as FirstIN,
    max(convert(char(5), LogOut,108)) as LastOUT
from Employee
group by UserId, [date]
Run Code Online (Sandbox Code Playgroud)

员工表

UserID   ShiftName      Start   End     
2267     Night Shift-1  17:30   02:30 
Run Code Online (Sandbox Code Playgroud)

期望输出

UserID LogIn                    LogOut                    LogDate
2267   2016-01-04 20:52:08.000  2016-01-04 22:09:22.000   2016-01-04 00:00:00.000
2267   2016-01-04 23:00:07.000  2016-01-04 23:00:07.000   2016-01-04 00:00:00.000
2267   2016-01-05 00:35:46.000  2016-01-05 00:35:46.000   2016-01-05 00:00:00.000
2267   2016-01-05 01:02:31.000  2016-01-05 03:57:16.000   2016-01-05 00:00:00.000
2267   2016-01-05 18:43:50.000  2016-01-05 19:05:04.000   2016-01-05 00:00:00.000
2267   2016-01-05 19:10:20.000  2016-01-05 22:26:00.000   2016-01-05 00:00:00.000
2267   2016-01-05 23:27:24.000  2016-01-05 23:27:24.000   2016-01-05 00:00:00.000
2267   2016-01-06 03:45:16.000  2016-01-06 03:45:16.000   2016-01-06 00:00:00.000
Run Code Online (Sandbox Code Playgroud)

Jul*_*eur 6

此查询LogIn按午夜 (0=00:00) 和班次开始之间的分钟数移动日期:

  • 17:30(开始)变为00:00
  • 2:30 变为 9:00。
  • 2016-01-06 03:45:16.0000000 变成 2016-01-05 10:15:16.0000000
  • ...

它用于获取班次的日期,然后可以在GROUP BY.

询问:

WITH s AS (
    SELECT s.UserID, e.LogIn, e.LogOut
        , [DATE] = CAST(DATEADD(minute, DATEDIFF(minute, s.[Start], 0), e.LogIn) as date)
    FROM @Shifts s
    INNER JOIN @Employees e ON s.UserID = e.UserID 
)
SELECT s.UserID, [DATE]
    , FirstIN = CAST(MIN(LogIn) as time)
    , LastOut = CAST(MAX(LogOut) as time)
FROM s
GROUP BY s.UserID, [DATE];
Run Code Online (Sandbox Code Playgroud)

请参阅SQL 小提琴

输出:

UserID  DATE        FirstIN             LastOut
2267    2016-01-04  20:52:08.0000000    03:57:16.0000000
2267    2016-01-05  18:43:50.0000000    03:45:16.0000000
Run Code Online (Sandbox Code Playgroud)

早到晚走:

如果有人迟到一点,它应该可以正常工作。

如果有人提前到达,您可以在 DATEADD 中添加一些时间,例如:

[DATE] = CAST(DATEADD(minute, 90 + DATEDIFF(minute, s.[Start], 0), e.LogIn) as date)
Run Code Online (Sandbox Code Playgroud)

这里增加了 90 分钟。这意味着,如果有人提前 90 分钟到达,则将计入当天。它将用于从 16:00 开始使用您的样本登录(17:30 - 90 分钟) 如果员工提前 2 小时(> 90 分钟)到达,则计为前一天。

工作时间:

FirstIn 和 LastOut 之间的小时数计算如下:

DATEDIFF(hour, MIN(LogIn), MAX(LogOut))
Run Code Online (Sandbox Code Playgroud)

或者像这样:

DATEADD(minute, DATEDIFF(minute, MIN(LogIn), MAX(LogOut)), CAST('' as time))
Run Code Online (Sandbox Code Playgroud)

工时输出:

UserID  DATE        FirstIN             LastOut             WorkHours   WorkTime
2267    2016-01-04  20:52:08.0000000    03:57:16.0000000    7           07:05:00.0000000
2267    2016-01-05  18:43:50.0000000    03:45:16.0000000    9           09:02:00.0000000
Run Code Online (Sandbox Code Playgroud)