需求分析
- 週期:從今日起 7 天。
- 每日時段:06:00–23:00,共 18 個整點時段。
- 分組:上午(06-11)、下午(12-17)、晚上(18-23)。
- 狀態:時段滿額 →「忙碌」,否則「空閒」。
建議資料表結構
方案一:單表按時段記錄(簡單直觀)
CREATE TABLE `schedule` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`work_date` DATE NOT NULL COMMENT '排班日期',
`hour_slot` TINYINT UNSIGNED NOT NULL COMMENT '0-23 整點',
`period` ENUM('morning','afternoon','night') NOT NULL COMMENT '時段分組',
`capacity` SMALLINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '最大容納人數',
`booked` SMALLINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '已預約人數',
`status` ENUM('free','busy') AS (CASE WHEN booked >= capacity THEN 'busy' ELSE 'free' END) STORED,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_date_hour` (`work_date`, `hour_slot`),
KEY `idx_date_period` (`work_date`, `period`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- 優點:查詢單日/單時段極快,狀態自動計算。
- 缺點:7天×18小時=126 列,資料量極小,無效能壓力。
方案二:按時段分組彙總(原答案風格)
CREATE TABLE `schedule_daily` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`work_date` DATE NOT NULL,
`day_of_week` TINYINT UNSIGNED NOT NULL COMMENT '1-7',
`morning_cap` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
`morning_booked` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
`afternoon_cap` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
`afternoon_booked` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
`night_cap` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
`night_booked` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_date` (`work_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- 狀態判斷在應用層:
morning_booked >= morning_cap ? 'busy' : 'free'。
- 適合固定三時段、容量固定的簡單場景。
擴充建議
- 若需支援多地點/多部門:增加
location_id、dept_id,聯合唯一鍵。
- 若需彈性時段:改用方案一,
period 可由應用層根據 hour_slot 計算。
- 索引優化:高頻查詢「某日期某時段狀態」→ 單表方案
uk_date_hour 覆蓋;彙總方案 uk_date 覆蓋。
狀態自動維護觸發器(可選)
CREATE TRIGGER `trg_schedule_booked` BEFORE UPDATE ON `schedule`
FOR EACH ROW BEGIN
IF NEW.booked >= NEW.capacity THEN SET NEW.status = 'busy';
ELSE SET NEW.status = 'free'; END IF;
END;