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

SQL 查詢某月份包含多少個星期日:通用邏輯與跨資料庫實作

     編輯:關於SqlServer

計算指定月份包含多少個星期日(或任意週幾),是報表、排程、薪資試算常見需求。本文提供通用集合思維解法:以數字序列表(Tally Table)產生該月所有日期,再套用日期函數篩選目標週幾並計數。並針對 MySQL、SQL Server、PostgreSQL、Oracle 提供對應語法。

核心邏輯三步驟

  1. 確定目標月份首日(如 '2006-09-01')。
  2. 用數字序列表產生 0 到 (該月天數-1) 的整數,加到首日產生該月所有日期。
  3. 對每個日期套用 WEEKDAY()/DAYOFWEEK()/DATEPART(WEEKDAY, ...) 判斷是否為星期日,SUM(CASE...) 計數。

建立通用數字序列表(一次性建立,永久複用)

CREATE TABLE dbo.Integers (i INT NOT NULL PRIMARY KEY);
INSERT INTO dbo.Integers (i) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
-- 如需更大範圍,可跨表 Cartesian Product 擴展至百萬級

各資料庫完整查詢範例

MySQL / MariaDB

SET @day1 = '2006-09-01';

SELECT COUNT(*) AS sundays
FROM (
    SELECT DATE_ADD(@day1, INTERVAL (10*tens.i + units.i) DAY) AS adate
    FROM Integers AS tens
    CROSS JOIN Integers AS units
    WHERE DATE_ADD(@day1, INTERVAL (10*tens.i + units.i) DAY) < DATE_ADD(@day1, INTERVAL 1 MONTH)
) d
WHERE DAYOFWEEK(adate) = 1;  -- 1 = Sunday

SQL Server (T-SQL)

DECLARE @day1 DATE = '20060901';

SELECT COUNT(*) AS sundays
FROM (
    SELECT DATEADD(DAY, 10*tens.i + units.i, @day1) AS adate
    FROM Integers AS tens
    CROSS JOIN Integers AS units
    WHERE DATEADD(DAY, 10*tens.i + units.i, @day1) < DATEADD(MONTH, 1, @day1)
) d
WHERE DATEPART(WEEKDAY, adate) = 1;  -- 預設 1=Sunday,受 SET DATEFIRST 影響
-- 更安全寫法:WHERE (DATEPART(WEEKDAY, adate) + @@DATEFIRST - 1) % 7 + 1 = 7

PostgreSQL

SELECT COUNT(*) AS sundays
FROM generate_series(
    DATE '2006-09-01',
    DATE '2006-09-01' + INTERVAL '1 month' - INTERVAL '1 day',
    INTERVAL '1 day'
) AS adate
WHERE EXTRACT(ISODOW FROM adate) = 7;  -- ISODOW: 1=Mon ... 7=Sun

Oracle

SELECT COUNT(*) AS sundays
FROM (
    SELECT TRUNC(TO_DATE('2006-09-01', 'YYYY-MM-DD')) + LEVEL - 1 AS adate
    FROM dual
    CONNECT BY LEVEL <= (LAST_DAY(TO_DATE('2006-09-01', 'YYYY-MM-DD')) - TRUNC(TO_DATE('2006-09-01', 'YYYY-MM-DD')) + 1)
)
WHERE TO_CHAR(adate, 'DY', 'NLS_DATE_LANGUAGE=AMERICAN') = 'SUN';

進階:內建函數單語句解法(無需輔助表)

現代資料庫多支援直接計算:

  • SQL Server:DATEDIFF(DAY, @firstDay, @lastDay) / 7 + CASE WHEN DATEPART(WEEKDAY, @firstDay) <= 1 AND 1 <= DATEPART(WEEKDAY, @lastDay) THEN 1 ELSE 0 END(需處理跨週邊界)。
  • PostgreSQL:EXTRACT(DAY FROM (DATE_TRUNC('MONTH', d) + INTERVAL '1 MONTH - 1 DAY') - DATE_TRUNC('MONTH', d)) / 7 + ...

建議:數字序列表法通用性最強、邏輯清晰、易除錯,適合大多數場景;極高頻呼叫時可考慮內建函數優化。

擴展應用

  • 計算工作日數:排除週六/週日與假日表。
  • 產生月曆矩陣:同邏輯加上 WEEK(adate)、DAY(adate) 即可輸出前端渲染所需結構。
  • 任意週幾計數:將 1(Sunday)替換為 2-7(Monday-Saturday)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved