首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 查詢排除週末的 N 個工作日前日期:行事曆表法與純 SQL 方案

     編輯:MySQL 資料庫相關知識

業務需求

取得「當前日期往前推 5 個工作日」的日期,週六、週日不計算在內;節假日同理。

最佳實踐:行事曆表

CREATE TABLE calendar (
  cal_date DATE PRIMARY KEY,
  is_workday TINYINT(1) NOT NULL DEFAULT 1,  -- 1=工作日 0=休息日
  memo VARCHAR(50)
);

-- 初始化 10 年資料
INSERT INTO calendar (cal_date, is_workday)
SELECT d, CASE WHEN DAYOFWEEK(d) IN (1,7) THEN 0 ELSE 1 END
FROM (
  SELECT DATE_ADD('2020-01-01', INTERVAL seq DAY) AS d
  FROM seq_0_to_3650  -- 需自建序列表或遞迴 CTE
) t;

查詢「5 個工作日前」

SELECT MAX(cal_date) AS target_date
FROM calendar
WHERE cal_date < CURDATE()
  AND is_workday = 1
  AND (
    SELECT COUNT(*) FROM calendar c2
    WHERE c2.cal_date <= calendar.cal_date
      AND c2.cal_date < CURDATE()
      AND c2.is_workday = 1
  ) <= 5;

純 SQL 方案(MySQL 8.0+ CTE,無需額外表)

WITH RECURSIVE workdays AS (
  SELECT DATE_SUB(CURDATE(), INTERVAL 1 DAY) AS d, 1 AS cnt
  UNION ALL
  SELECT DATE_SUB(d, INTERVAL 1 DAY),
         cnt + CASE WHEN DAYOFWEEK(DATE_SUB(d, INTERVAL 1 DAY)) IN (1,7) THEN 0 ELSE 1 END
  FROM workdays
  WHERE cnt < 5
)
SELECT d FROM workdays WHERE cnt = 5 ORDER BY d DESC LIMIT 1;

節假日擴充

在 calendar 表手動將節假日 is_workday=0,或建立 holiday 表 LEFT JOIN 排除。純 SQL 方案則需在 CTE 中硬編碼或 NOT IN (SELECT holiday_date FROM holidays)。

效能建議

  • 行事曆表配合索引 (is_workday, cal_date),查詢極快且易維護。
  • 純 SQL 遞迴 CTE 適合臨時查詢、資料量小場景。
  • 高頻呼叫建議將結果快取於 Redis,每日 00:00 重算。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved