SQL Server 2022 新函数:DATETRUNC 日期截断详解

前言

DATETRUNC 是 SQL Server 2022 引入的日期截断函数,可以将日期/时间值截断到指定的精度(如截断到年、月、周、日、小时等)。在统计报表、时间分组等场景中非常实用,比以前用 CONVERTDATEADDDATEDIFF 组合实现的写法简洁得多。

语法

复制代码
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

返回值:与输入参数相同的数据类型,小于截断精度的部分全部归零。

复制代码
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)

一、按日截断(去掉时间部分)

复制代码
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 类型。


二、按月截断(统计月度数据)

复制代码
-- 按月汇总销售额
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

老写法对比:

复制代码
-- 以前的写法,需要组合多个函数
GROUP BY DATEADD(month, DATEDIFF(month, 0, OrderDate), 0)
-- 或者
GROUP BY YEAR(OrderDate), MONTH(OrderDate)

DATETRUNC 写法更直观,且结果直接是 DATETIME2 类型,可用于后续日期计算。


三、按季度截断

复制代码
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 周,周一为第一天)

复制代码
SELECT 
    OrderID,
    OrderDate,
    DATETRUNC(week,     OrderDate) AS 本周起始_周日,
    DATETRUNC(iso_week, OrderDate) AS 本周起始_周一
FROM #Orders
  • week:以周日为每周第一天(受 DATEFIRST 设置影响)
  • iso_week:以周一为每周第一天(ISO 8601 标准,不受 DATEFIRST 影响)

推荐业务场景中优先使用 iso_week,结果更可预期。


五、按小时截断(适合流量/日志分析)

复制代码
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 结合:计算距本月初的天数

复制代码
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 环境中替换老写法。

相关推荐
qq_189807031 天前
SQL多表嵌套查询数据重复怎么办_使用DISTINCT去重优化策略
jvm·数据库·python
m0_747854521 天前
mysql如何设置数据库连接字符编码_修改default-character
jvm·数据库·python
Wyz201210241 天前
如何在 React 中正确将父组件函数传递给子组件并触发调用
jvm·数据库·python
2401_865439631 天前
Go语言如何用logrus_Go语言logrus日志框架教程【技巧】
jvm·数据库·python
NotFound4861 天前
CSS如何利用Flex实现悬浮的侧边按钮组_利用fixed定位与flex布局组合
jvm·数据库·python
神の愛1 天前
@Pattern,@NotBlank
数据库·mysql
qq_189807031 天前
Golang怎么实现RBAC权限控制_Golang如何用casbin实现基于角色的访问控制系统【教程】
jvm·数据库·python
vegetablec1 天前
CSS如何处理相对定位留下的原本占位空白_认识到相对定位不会脱离文档流,需借助负margin消除视觉空隙
jvm·数据库·python
2401_832635581 天前
HTML怎么创建响应式图片备选方案_HTML srcset与sizes结构【详解】
jvm·数据库·python
浅念-1 天前
从LeetCode入门位运算:常见技巧与实战题目全解析
数据结构·数据库·c++·笔记·算法·leetcode·牛客