DATETRUNC 是 SQL Server 2022 引入的日期截断函数,可以将日期/时间值截断到指定的精度(如截断到年、月、周、日、小时等)。在统计报表、时间分组等场景中非常实用,比以前用 CONVERT、DATEADD、DATEDIFF 组合实现的写法简洁得多。
语法
DATETRUNC ( datepart, date )
| 参数 |
说明 |
| datepart |
截断精度,支持:year、quarter、month、week、iso_week、dayofyear、day、hour、minute、second、millisecond、microsecond、nanosecond |
| date |
日期/时间表达式,支持 date、time、datetime、datetime2、datetimeoffset、smalldatetime |
返回值:与输入参数相同的数据类型,小于截断精度的部分全部归零。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
CREATE TABLE #Orders (
OrderID INT,
CustomerID INT,
OrderDate DATETIME2,
Amount DECIMAL(10, 2)
)
INSERT INTO #Orders VALUES
(1, 101, '2024-03-15 09:32:47.123', 1500.00),
(2, 102, '2024-03-15 14:05:22.456', 800.00),
(3, 101, '2024-03-20 11:18:33.789', 2300.00),
(4, 103, '2024-04-02 08:55:01.234', 620.00),
(5, 102, '2024-04-18 16:44:59.567', 1100.00),
(6, 101, '2024-05-07 10:22:15.890', 3200.00),
(7, 103, '2024-05-25 13:30:45.123', 950.00),
(8, 102, '2024-06-10 09:15:30.456', 1750.00)
|
一、按日截断(去掉时间部分)
|
1
2
3
4
5
|
SELECT
OrderID,
OrderDate,
DATETRUNC(day, OrderDate) AS 截断到日
FROM #Orders
|
结果:
| OrderID |
OrderDate |
截断到日 |
| 1 |
2024-03-15 09:32:47.123 |
2024-03-15 00:00:00 |
| 2 |
2024-03-15 14:05:22.456 |
2024-03-15 00:00:00 |
| 3 |
2024-03-20 11:18:33.789 |
2024-03-20 00:00:00 |
| ... |
... |
... |
老写法对比:CONVERT(DATE, OrderDate) 或 CAST(OrderDate AS DATE),注意 DATETRUNC 保留原始数据类型(返回 DATETIME2),而不是转为 DATE 类型。
二、按月截断(统计月度数据)
|
1
2
3
4
5
6
7
8
|
-- 按月汇总销售额
SELECT
DATETRUNC(month, OrderDate) AS 月份,
COUNT(*) AS 订单数,
SUM(Amount) AS 总金额
FROM #Orders
GROUP BY DATETRUNC(month, OrderDate)
ORDER BY 月份
|
结果:
| 月份 |
订单数 |
总金额 |
| 2024-03-01 00:00:00 |
3 |
4600.00 |
| 2024-04-01 00:00:00 |
2 |
1720.00 |
| 2024-05-01 00:00:00 |
2 |
4150.00 |
| 2024-06-01 00:00:00 |
1 |
1750.00 |
老写法对比:
|
1
2
3
4
|
-- 以前的写法,需要组合多个函数
GROUP BY DATEADD(month, DATEDIFF(month, 0, OrderDate), 0)
-- 或者
GROUP BY YEAR(OrderDate), MONTH(OrderDate)
|
DATETRUNC 写法更直观,且结果直接是 DATETIME2 类型,可用于后续日期计算。
三、按季度截断
|
1
2
3
4
5
6
7
|
SELECT
DATETRUNC(quarter, OrderDate) AS 季度起始日,
COUNT(*) AS 订单数,
SUM(Amount) AS 总金额
FROM #Orders
GROUP BY DATETRUNC(quarter, OrderDate)
ORDER BY 季度起始日
|
结果:
| 季度起始日 |
订单数 |
总金额 |
| 2024-01-01 00:00:00 |
5 |
6320.00 |
| 2024-04-01 00:00:00 |
3 |
3800.00 |
四、按周截断(ISO 周,周一为第一天)
|
1
2
3
4
5
6
|
SELECT
OrderID,
OrderDate,
DATETRUNC(week, OrderDate) AS 本周起始_周日,
DATETRUNC(iso_week, OrderDate) AS 本周起始_周一
FROM #Orders
|
- week:以周日为每周第一天(受 DATEFIRST 设置影响)
- iso_week:以周一为每周第一天(ISO 8601 标准,不受 DATEFIRST 影响)
推荐业务场景中优先使用 iso_week,结果更可预期。
五、按小时截断(适合流量/日志分析)
|
1
2
3
4
5
6
|
SELECT
OrderID,
OrderDate,
DATETRUNC(hour, OrderDate) AS 截断到小时,
DATETRUNC(minute, OrderDate) AS 截断到分钟
FROM #Orders
|
结果:
| OrderID |
OrderDate |
截断到小时 |
截断到分钟 |
| 1 |
2024-03-15 09:32:47.123 |
2024-03-15 09:00:00 |
2024-03-15 09:32:00 |
| 2 |
2024-03-15 14:05:22.456 |
2024-03-15 14:00:00 |
2024-03-15 14:05:00 |
六、与 DATEDIFF 结合:计算距本月初的天数
|
1
2
3
4
5
|
SELECT
OrderID,
OrderDate,
DATEDIFF(day, DATETRUNC(month, OrderDate), OrderDate) AS 当月第几天
FROM #Orders
|
结果:
| OrderID |
OrderDate |
当月第几天 |
| 1 |
2024-03-15 09:32:47.123 |
14 |
| 4 |
2024-04-02 08:55:01.234 |
1 |
| 6 |
2024-05-07 10:22:15.890 |
6 |
七、支持的 datepart 汇总
| datepart |
示例输入 |
截断结果 |
| year |
2024-03-15 09:32 |
2024-01-01 00:00 |
| quarter |
2024-05-15 09:32 |
2024-04-01 00:00 |
| month |
2024-03-15 09:32 |
2024-03-01 00:00 |
| week |
2024-03-15(周五) |
2024-03-10(本周周日) |
| iso_week |
2024-03-15(周五) |
2024-03-11(本周周一) |
| day |
2024-03-15 09:32:47 |
2024-03-15 00:00:00 |
| hour |
2024-03-15 09:32:47 |
2024-03-15 09:00:00 |
| minute |
2024-03-15 09:32:47 |
2024-03-15 09:32:00 |
| second |
2024-03-15 09:32:47.123 |
2024-03-15 09:32:47 |
兼容性说明
| 版本 |
支持情况 |
| SQL Server 2022 及以上 |
? 支持 |
| SQL Server 2019 及以下 |
? 不支持 |
| Azure SQL Database |
? 支持(2022年4月起) |
总结
DATETRUNC 填补了 SQL Server 长期以来缺少日期截断专用函数的空白。以前需要 DATEADD + DATEDIFF 组合才能实现的逻辑,现在一个函数搞定:
- 统计报表按年/月/季度/周分组:GROUP BY DATETRUNC(month, 日期列)
- 去除时间部分:DATETRUNC(day, 日期列)(保留原类型,不变成 DATE)
- 日志分析按小时/分钟汇总:GROUP BY DATETRUNC(hour, 日期列)
简洁、直观,推荐在 SQL Server 2022 环境中替换老写法。
|