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

SQL Server 截取日期時間部分:DATEPART/YEAR/MONTH/DAY 與 DATEADD/DATEDIFF 兩大流派

     編輯:MySQL 資料庫相關知識

統計報表常需「按年/月/日群組」,但資料欄位為精確 DATETIME。兩大主流截取法各有優劣。

方法一:日期部份函數 (直觀、可讀性高)

-- 取年月日組合成日期 (歸零時間)
CAST(
    STR(YEAR(GETDATE())) + '/' +
    STR(MONTH(GETDATE())) + '/' +
    STR(DAY(GETDATE()))
AS DATETIME)

-- 僅需年月
CAST(
    STR(YEAR(GETDATE())) + '/' +
    STR(MONTH(GETDATE())) + '/01'
AS DATETIME)

或直接用 DATEPART / YEAR / MONTH / DAY 於 GROUP BY:

SELECT YEAR(OrderDate) AS yr, MONTH(OrderDate) AS mo, COUNT(*)
FROM Orders GROUP BY YEAR(OrderDate), MONTH(OrderDate);

方法二:日期運算法 (效能佳、索引友善)

-- 取得「所屬月份第一天 00:00:00」
DATEADD(MONTH, DATEDIFF(MONTH, 0, OrderDate), 0)

-- 原理:算出與基準日 1900-01-01 相差月數,再加回基準日
-- 優點:可直接套用在 WHERE 條件,利用 OrderDate 索引 Seek
WHERE OrderDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
  AND OrderDate <  DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())+1, 0)

效能對比建議

場景建議寫法理由
SELECT 清單 / GROUP BYYEAR()/MONTH()/DATEPART()可讀性高,編譯器可優化
WHERE 篩選 / JOIN 條件DATEADD/DATEDIFF 歸零法保持 SARGable,可用索引 Range Seek
計算「本月第一天」常數DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)單一運算,無函數包裹欄位

反模式警示

-- 錯誤:對欄位套用函數導致索引失效
WHERE YEAR(OrderDate) = 2023 AND MONTH(OrderDate) = 10

-- 正確:改用區間比較
WHERE OrderDate >= '2023-10-01' AND OrderDate < '2023-11-01'
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved