651 字
3 分钟
SQL Server 日期查询实战:从基础到高级优化技巧
引言
在数据库开发中,日期筛选是最高频的操作之一。虽然 DATEDIFF 和 DATEADD 能解决 90% 的问题,但在处理大数据量时,错误的写法会导致查询效率直线下降。本文不仅分享常用的查询技巧,还将教你如何编写“索引友好”的日期 SQL。
一、 常用时间段筛选(常规写法)
这些语句非常适合报表统计或小规模数据查询。
1. 今天、昨天与过去 N 天
- 今天:
WHERE DATEDIFF(dd, [DateColumn], GETDATE()) = 0 - 昨天:
WHERE DATEDIFF(dd, [DateColumn], GETDATE()) = 1 - 过去 7 天内:
WHERE DATEDIFF(dd, [DateColumn], GETDATE()) <= 7
2. 本月与本年
- 本月:
WHERE DATEDIFF(mm, [DateColumn], GETDATE()) = 0 - 本年:
WHERE DATEDIFF(yy, [DateColumn], GETDATE()) = 0
二、 进阶日期计算(精准控制)
3. 获取边界日期(月初、月末)
在旧版本中,我们常用 DATEADD 组合计算,但在 SQL Server 2012 之后,有更优雅的选择:
- 本月第一天:
SELECT DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0);- 本月最后一天(新推荐):
SELECT EOMONTH(GETDATE()); -- SQL Server 2012+ 支持- 本月有多少天:
SELECT DAY(EOMONTH(GETDATE()));4. 计算周一(不受特定语言设置影响)
直接使用 DATEDIFF 计算基准日期(0 代表 1900-01-01,那是周一)的差值:
SELECT DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) AS ThisMonday;三、 性能优化:编写索引友好的查询 (SARG)
这是本文最重要的部分。 > 警惕:当你写 WHERE DATEDIFF(dd, CreateTime, GETDATE()) = 0 时,SQL Server 必须对表中每一行执行函数计算,这会导致索引失效(Index Scan)。
优化方案:计算范围,而不是计算字段。
如果你想查询今天的数据,推荐写法:
-- 这种写法支持索引寻址 (Index Seek)DECLARE @Today DATE = GETDATE();SELECT * FROM 表名WHERE CreateTime >= CAST(@Today AS DATETIME) AND CreateTime < CAST(DATEADD(dd, 1, @Today) AS DATETIME);四、 常用函数速查表
| 函数 | 说明 | 示例 |
|---|---|---|
GETDATE() | 获取当前系统时间 | 2024-01-14 14:30:00 |
DATEPART(dw, dt) | 返回周几(数字) | 1 (周日) 或 2 (周一) |
DATENAME(month, dt) | 返回月份名称 | January 或 一月 |
CONVERT(varchar, dt, 23) | 格式化日期 | 2024-01-14 (ISO 格式) |
五、 常见问题 FAQ
-
Q: 如何计算两个日期间隔的分钟数?
-
SELECT DATEDIFF(mi, '2024-01-14 10:00', GETDATE()); -
Q: 为什么我的周一计算不对?
-
SQL Server 的
DATEFIRST设置可能不同。建议使用本文“月初”类似的基准日期计算法,它不受系统语言设置(@@DATEFIRST)的影响。
总结
掌握日期函数只是第一步,意识到函数对索引的影响才是进阶资深开发者的关键。在处理百万级以上的数据表时,请务必使用 Range Query(范围查询)代替字段上的 DATEDIFF。
SQL Server 日期查询实战:从基础到高级优化技巧
https://sw.rscclub.website/posts/sqlcxjq/