首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 輪班排程邏輯實作:用 Shifts 表解決跨日、遲到、加班的分組難題

     編輯:關於SqlServer

業務場景:三班制與彈性打卡的衝突

公司實施三班制:
第一班 00:00–08:00、第二班 08:00–16:00、第三班 16:00–24:00。
員工以電子打卡記錄存入 SQL Server,但實際情況複雜:

  • 員工不一定準時打卡(早到/遲到)。
  • 工作時間可能跨越班次邊界(如加班到隔天凌晨)。
  • 甚至需新增夜班,仍歸屬第三班管理。

單純用 CASE 硬編碼時間區間,無法應對上述彈性,維護成本極高。

核心解法:建立 Shifts 參數表 + 動態查詢

將班次定義外部化為資料表 Shifts,包含 ShiftName、StartTime、StopTime 欄位。查詢時依打卡時間動態比對,自動適應班次調整。

Shifts 表結構範例

CREATE TABLE ShiftWork.Shifts (
    ShiftName VARCHAR(20),
    StartTime TIME,
    StopTime  TIME
);
INSERT INTO ShiftWork.Shifts VALUES
('第一班', '00:00:00', '07:59:59.999'),
('第二班', '08:00:00', '15:59:59.999'),
('第三班', '16:00:00', '23:59:59.999');

關鍵細節:結束時間設為 23:59:59.999(含毫秒),避免邊界值遺漏;第三班跨午夜需特別處理。

動態判斷班次的查詢邏輯

DECLARE @PunchTime TIME = '22:59:59'; -- 打卡時間參數

SELECT TOP 1 ShiftName
FROM ShiftWork.Shifts
WHERE StartTime <= @PunchTime
ORDER BY StartTime DESC;

原理:以 StartTime 降序排列,找到「小於等於打卡時間」的最近一筆開始時間,即為所屬班次。此法完美解決第三班跨午夜邊界問題(因 00:00–07:59 的 StartTime 最小,若打卡 01:00 會正確落入第一班)。

進階應用:直接套用至打卡記錄表

無需額外建表,可將邏輯內嵌於查詢或檢視表中:

SELECT 
    tc.EmployeeID,
    tc.PunchTime,
    (SELECT TOP 1 ShiftName 
     FROM ShiftWork.Shifts 
     WHERE StartTime <= CAST(tc.PunchTime AS TIME) 
     ORDER BY StartTime DESC) AS ShiftName
FROM TimeCards tc;

若班次異動,僅需更新 Shifts 表,所有報表即時生效,零程式碼修改。

測試驗證建議

  • 邊界值:07:59:59.999、08:00:00、15:59:59.999、16:00:00、23:59:59.999、00:00:00。
  • 跨日加班:打卡 23:30、隔天 00:30,分別歸屬第三班、第一班。
  • 班次調整:修改 Shifts 表 StartTime/StopTime,觀察查詢結果即時變化。

結語

以參數表驅動邏輯取代硬編碼,是處理複雜排程規則的最佳實踐。Shifts 表不僅解決輪班分組,更為未來排班彈性化、多班次共存奠定基礎。下次面對「時間區間分組」需求,請先問自己:能不能抽成一張表?

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved