公司實施三班制:
第一班 00:00–08:00、第二班 08:00–16:00、第三班 16:00–24:00。
員工以電子打卡記錄存入 SQL Server,但實際情況複雜:
單純用 CASE 硬編碼時間區間,無法應對上述彈性,維護成本極高。
將班次定義外部化為資料表 Shifts,包含 ShiftName、StartTime、StopTime 欄位。查詢時依打卡時間動態比對,自動適應班次調整。
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 表,所有報表即時生效,零程式碼修改。
以參數表驅動邏輯取代硬編碼,是處理複雜排程規則的最佳實踐。Shifts 表不僅解決輪班分組,更為未來排班彈性化、多班次共存奠定基礎。下次面對「時間區間分組」需求,請先問自己:能不能抽成一張表?