SELECT ISBN,BookName,INTime 数据录入时间 FROM bookinfo_zerobasis WHERE INTime BETWEEN DATEADD(DAY,-1,GETDATE()) AND GETDATE();
这条 SQL 语句的作用是:查询过去 24 小时内(从昨天同一时刻到现在)录入的图书信息。
让我逐部分详细解释:
一、整体逻辑
sql
SELECT ISBN, BookName, INTime 数据录入时间 FROM bookinfo_zerobasis WHERE INTime BETWEEN DATEADD(DAY, -1, GETDATE()) AND GETDATE();
查询范围:过去 24 小时内录入的图书
动态日期:使用
GETDATE()获取当前时间,因此每次查询结果都会不同
二、各部分详解
1. GETDATE()
获取当前系统日期和时间
例如:
2026-04-14 15:30:25.123
2. DATEADD(DAY, -1, GETDATE())
DATEADD函数:在日期上增加或减少指定时间间隔DAY, -1:减去 1 天结果:昨天此时刻
例如:如果现在是
2026-04-14 15:30:25,则结果为2026-04-13 15:30:25
3. BETWEEN ... AND ...
范围包含两端
查询
INTime在昨天此时刻到当前时刻之间的所有记录
4. INTime 数据录入时间
缺少
AS关键字(但某些数据库允许省略)标准写法应为:
INTime AS 数据录入时间
三、实际示例
假设当前时间是 2026-04-14 15:30:25:
sql
WHERE INTime BETWEEN '2026-04-13 15:30:25' AND '2026-04-14 15:30:25'
会查询出:
昨天下午 3:30:25 之后录入的书
到今天下午 3:30:25 之前录入的书
恰好 24 小时的时间窗口
四、⚠️ 潜在问题与改进建议
问题 1:BETWEEN 在精确时间下的行为
如果
INTime包含毫秒,边界值的毫秒部分可能导致漏数据更安全的写法(推荐):
sql
SELECT ISBN, BookName, INTime AS 数据录入时间FROM bookinfo_zerobasisWHERE INTime >= DATEADD(DAY, -1, GETDATE()) AND INTime < GETDATE();
问题 2:缺少 AS 关键字
当前写法
INTime 数据录入时间在某些数据库(如 Oracle)会报错标准写法:
sql
SELECT ISBN, BookName, INTime AS 数据录入时间
问题 3:时区问题
GETDATE()返回的是数据库服务器的本地时间如果用户和服务器在不同时区,查询结果可能不符合预期
解决方案:使用
GETUTCDATE()统一使用 UTC 时间
sql
WHERE INTime BETWEEN DATEADD(DAY, -1, GETUTCDATE()) AND GETUTCDATE()
问题 4:性能问题
对
INTime列使用函数或范围查询通常没问题但确保
INTime列有索引,否则大表查询会很慢
五、常见变体需求
| 需求 | 写法 |
|---|---|
| 今天录入的数据 | WHERE INTime >= CAST(GETDATE() AS DATE) |
| 昨天全天数据 | WHERE INTime >= DATEADD(DAY, -1, CAST(GETDATE() AS DATE)) AND INTime < CAST(GETDATE() AS DATE) |
| 过去 7 天 | WHERE INTime >= DATEADD(DAY, -7, GETDATE()) |
| 本月数据 | WHERE INTime >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) |
六、总结
| 项目 | 说明 |
|---|---|
| 功能 | 查询过去 24 小时录入的图书 |
| 优点 | 动态时间,无需手动改日期 |
| 缺点 | 边界值可能漏数据;依赖服务器时区 |
| 适用场景 | 实时监控、增量同步、今日新增统计 |
| 建议改进 | 用 >= 和 < 替代 BETWEEN;明确时区 |
再讲一下DATEADD(DAY, -1, GETDATE())
DATEADD(DAY, -1, GETDATE()) 详解
这是一个日期计算函数,用于获取昨天此时的准确时间。
一、函数拆解
sql
DATEADD(DAY, -1, GETDATE())
| 组成部分 | 含义 | 示例值 |
|---|---|---|
GETDATE() | 获取当前日期时间 | 2026-04-14 15:30:25.123 |
DAY | 指定时间单位是天 | 按天进行计算 |
-1 | 减少的数量(负数表示往前) | 减去 1 天 |
DATEADD | 在指定日期上增加/减少时间 | 执行计算 |
结果:2026-04-13 15:30:25.123(精确到毫秒)
二、参数详解
1. 第一个参数:时间单位
常用单位有:
| 单位 | 说明 | 示例 |
|---|---|---|
YEAR / YY | 年 | DATEADD(YEAR, -1, GETDATE()) 去年今日 |
MONTH / MM | 月 | DATEADD(MONTH, -3, GETDATE()) 3个月前 |
DAY / DD | 天 | DATEADD(DAY, 7, GETDATE()) 7天后 |
HOUR / HH | 小时 | DATEADD(HOUR, 2, GETDATE()) 2小时后 |
MINUTE / MI | 分钟 | DATEADD(MINUTE, -30, GETDATE()) 30分钟前 |
SECOND / SS | 秒 | DATEADD(SECOND, 10, GETDATE()) 10秒后 |
2. 第二个参数:增减数量
正数:向未来增加
负数:向过去减少
零:不变
3. 第三个参数:基准日期
可以是:
GETDATE():当前时间'2024-01-01':指定日期表中的日期列:如
bookinfo_zerobasis.INTime
三、实际计算示例
假设当前时间是 2026-04-14 15:30:25.123
sql
SELECT GETDATE() AS 当前时间, DATEADD(DAY, -1, GETDATE()) AS 昨天此时, DATEADD(DAY, -2, GETDATE()) AS 前天此时, DATEADD(DAY, 1, GETDATE()) AS 明天此时, DATEADD(HOUR, -24, GETDATE()) AS 24小时前; -- 和减1天结果相同
结果:
| 当前时间 | 昨天此时 | 前天此时 | 明天此时 | 24小时前 |
|---|---|---|---|---|
| 2026-04-14 15:30:25.123 | 2026-04-13 15:30:25.123 | 2026-04-12 15:30:25.123 | 2026-04-15 15:30:25.123 | 2026-04-13 15:30:25.123 |
四、在 WHERE 条件中的作用
sql
WHERE INTime BETWEEN DATEADD(DAY, -1, GETDATE()) AND GETDATE()
执行过程:
GETDATE()先执行 →2026-04-14 15:30:25.123DATEADD(DAY, -1, ...)计算 →2026-04-13 15:30:25.123BETWEEN形成范围 →2026-04-13 15:30:25.123到2026-04-14 15:30:25.123查询落在该时间段的图书记录
结果:查询出最近24小时内录入的图书(精确到毫秒)
五、常见应用场景
1. 过去 N 天
sql
-- 过去 7 天WHERE INTime >= DATEADD(DAY, -7, GETDATE())-- 过去 30 天WHERE INTime >= DATEADD(DAY, -30, GETDATE())
2. 过去 N 小时
sql
-- 过去 6 小时WHERE INTime >= DATEADD(HOUR, -6, GETDATE())
3. 本月开始至今
sql
WHERE INTime >= DATEADD(DAY, -DAY(GETDATE()) + 1, CAST(GETDATE() AS DATE))
4. 上个月同期
sql
WHERE INTime BETWEEN DATEADD(MONTH, -1, DATEADD(DAY, -1, GETDATE())) AND DATEADD(DAY, -1, GETDATE())
六、与其他数据库的对比
| 数据库 | 昨天此时的写法 |
|---|---|
| SQL Server | DATEADD(DAY, -1, GETDATE()) |
| MySQL | DATE_SUB(NOW(), INTERVAL 1 DAY) |
| PostgreSQL | NOW() - INTERVAL '1 day' |
| Oracle | SYSDATE - 1 |
七、注意事项 ⚠️
1. 保留时间部分
DATEADD(DAY, -1, GETDATE())保留时分秒毫秒如果要查昨天全天(00:00:00 到 23:59:59),需用:
sql
-- 昨天开始DATEADD(DAY, -1, CAST(GETDATE() AS DATE))-- 或DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 1, 0)
2. 性能考虑
DATEADD在 WHERE 条件中不影响索引使用(只要列本身没被函数包裹)✅ 正确:
WHERE INTime >= DATEADD(DAY, -1, GETDATE())❌ 错误:
WHERE DATEADD(DAY, 1, INTime) >= GETDATE()(会导致索引失效)
3. 时区问题
GETDATE()返回服务器本地时间跨时区应用建议用
GETUTCDATE()
八、快速记忆
text
DATEADD(单位, 数量, 基准日期) ↓ ↓ ↓ DATEADD(DAY, -1, GETDATE()) ↑ ↑ ↑ 按天 减1天 从当前时间开始
理解为:从当前时间往回数 1 天,得到精确到毫秒的那个时间点