日期計算的本質是「從基準點 (1900-01-01) 計算間隔數,再加回基準點」。掌握此模式,任意時間粒度的「首/末」皆可推導。
DATEADD(interval, DATEDIFF(interval, 0, GETDATE()), 0)
0 隱式轉為 1900-01-01 00:00:00.000DATEDIFF 計算當前到基準點的間隔數DATEADD 將間隔數加回基準點,得到當前粒度的「零點」| 目標 | Interval | 代碼 |
|---|---|---|
| 本月第一天 | month (mm) | DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0) |
| 本周一 | week (wk) | DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) |
| 今年第一天 | year (yy) | DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0) |
| 本季第一天 | quarter (qq) | DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0) |
| 今日零點 | day (dd) | DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0) |
-- 本月最後一天 23:59:59.997
DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0))
-- 本周日 23:59:59.997
DATEADD(ms, -3, DATEADD(wk, DATEDIFF(wk, 0, GETDATE()) + 1, 0))
SET DATEFIRST 7 (美式:周日=1) — 默認SET DATEFIRST 1 (歐式:周一=1) — 影響 week/wk 計算SELECT @@DATEFIRSTSET DATEFIRST 或用 DATEPART(dw, ...) 配合邏輯判斷WHERE CreatedAt >= DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0)
AND CreatedAt < DATEADD(mm, DATEDIFF(mm, 0, GETDATE()) + 1, 0)
-- 精確捕獲「本月」數據,利用索引 SARGable
此模式無循環、無變量、單語句、SARGable,是 SQL 日期計算的「瑞士軍刀」。