在 SQL Server 開發與維護中,日期時間運算是極高頻的需求。無論是取得本月首尾日、本週一、季度邊界,還是依月、週、季篩選資料,掌握標準寫法能大幅提升效能與可維護性。本文整理 14 類常見場景,附上可直接複製的 T-SQL 範例,並說明關鍵函數原理,助你快速套用專案。
-- 方法 1:日期差運算(效能最佳)
SELECT DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0);
-- 方法 2:字串轉換(較直觀)
SELECT CONVERT(datetime, CONVERT(varchar(8), GETDATE(), 120) + '01', 120);
-- 方法 1:下月 1 日減 1 天
SELECT DATEADD(day, -1, CONVERT(datetime, CONVERT(varchar(8), DATEADD(month, 1, GETDATE()), 120) + '01', 120));
-- 方法 2:毫秒精度避免四捨五入問題
SELECT DATEADD(ms, -3, DATEADD(month, DATEDIFF(month, 0, GETDATE()) + 1, 0));
SELECT DATEADD(ms, -3, DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0));
SELECT DATEADD(week, DATEDIFF(week, 0, DATEADD(day, 6 - DATEPART(day, GETDATE()), GETDATE())), 0);
-- 本年第一天
SELECT DATEADD(year, DATEDIFF(year, 0, GETDATE()), 0);
-- 本年最後一天
SELECT DATEADD(ms, -3, DATEADD(year, DATEDIFF(year, 0, GETDATE()) + 1, 0));
-- 去年最後一天
SELECT DATEADD(ms, -3, DATEADD(year, DATEDIFF(year, 0, GETDATE()), 0));
SELECT DATEADD(quarter, DATEDIFF(quarter, 0, GETDATE()), 0);
SELECT DATEADD(week, DATEDIFF(week, 0, GETDATE()), 0);
建議使用「半開半閉區間」寫法(WHERE dt >= @start AND dt < @end),可用索引且避免函數導致掃描。下列為傳統 DATEPART 寫法,僅供參考:
SELECT * FROM tableName
WHERE DATEPART(month, theDate) = DATEPART(month, GETDATE())
AND DATEPART(year, theDate) = DATEPART(year, GETDATE());
SELECT * FROM tableName
WHERE DATEPART(week, theDate) = DATEPART(week, GETDATE())
AND DATEPART(year, theDate) = DATEPART(year, GETDATE());
SELECT * FROM tableName
WHERE DATEPART(quarter, theDate) = DATEPART(quarter, GETDATE())
AND DATEPART(year, theDate) = DATEPART(year, GETDATE());
-- 方法 1:簡潔
SELECT DATEDIFF(day, GETDATE(), DATEADD(month, 1, GETDATE()));
-- 方法 2:相容舊版
SELECT DATEDIFF(day,
DATEADD(month, DATEDIFF(month, '', GETDATE()), ''),
DATEADD(month, DATEDIFF(month, '', GETDATE()), '1900-02-01'));
SELECT DATENAME(weekday, GETDATE()); -- 回傳 'Monday'、'星期一' 等(視語系)
DATETIME 精度 3.33ms 導致的午夜歸屬問題。WHERE dt >= '2024-01-01' AND dt < '2024-02-01' 可用索引,優於函數包裹欄位。將上述片段收藏為程式碼片段或建立為資料庫函數,即可在專案中快速重用。記得根據資料型別(DATE、DATETIME2、DATETIMEOFFSET)微調精度,即可應對各種版本與雲端環境。