SQL时间范围查询是数据库开发中非常常见的场景,例如查询某个时间段内的订单、统计指定日期的访问量、分析最近一周的业务数据等。SQL中的BETWEEN操作符可以快速实现区间匹配,而结合时间函数使用后,可以进一步提升查询的灵活性和实用性。
BETWEEN操作符基础概念
BETWEEN是SQL提供的范围查询操作符,用于判断字段值是否处于指定区间内。其基本语法如下:
SELECT 字段名
FROM 表名
WHERE 字段名 BETWEEN 起始值 AND 结束值;BETWEEN包含边界值,也就是说以下查询:
SELECT *
FROM orders
WHERE order_time BETWEEN '2026-01-01' AND '2026-01-31';等价于:
SELECT *
FROM orders
WHERE order_time >= '2026-01-01'
AND order_time <= '2026-01-31';这里需要注意,BETWEEN默认是闭区间,起始时间和结束时间都会被包含。
时间字段结合BETWEEN实现日期范围查询
在实际业务中,数据库表通常会保存创建时间、更新时间等字段。例如订单表orders:
| 字段 | 类型 |
|---|---|
| id | int |
| user_id | int |
| order_time | datetime |
| amount | decimal |
如果需要查询2026年1月份创建的订单,可以使用:
SELECT *
FROM orders
WHERE order_time BETWEEN '2026-01-01 00:00:00'
AND '2026-01-31 23:59:59';这种写法可以准确覆盖整个月的数据。
如果只写:
WHERE order_time BETWEEN '2026-01-01'
AND '2026-01-31'部分数据库会将结束时间自动解析为:
2026-01-31 00:00:00导致当天其他时间的数据无法查询。因此,在处理datetime类型字段时,需要特别关注结束时间的精度问题。
使用时间函数动态生成查询范围
固定日期查询无法满足动态统计需求,例如查询最近7天数据、当前月份数据等。这时可以结合数据库提供的时间函数。
MySQL中结合DATE_SUB实现最近时间查询
查询最近7天创建的订单:
SELECT *
FROM orders
WHERE order_time BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY)
AND NOW();其中:
NOW()返回当前日期时间;
DATE_SUB()用于进行时间减法;
INTERVAL 7 DAY表示减去7天。
该方式适用于后台管理系统中的“最近一周数据”“近期交易记录”等功能。
使用CURDATE查询当天数据
如果只需要查询当天记录,可以结合CURDATE()函数:
SELECT *
FROM orders
WHERE order_time BETWEEN CURDATE()
AND DATE_ADD(CURDATE(), INTERVAL 1 DAY);相比直接写:
WHERE DATE(order_time)=CURDATE()这种方式通常更利于索引使用。
原因在于对字段使用函数转换可能导致数据库无法有效利用索引,而通过范围条件查询可以保持字段原始形式。
使用时间函数查询指定月份数据
统计某个月的数据是报表系统中的常见需求。
例如查询2026年8月所有订单:
SELECT *
FROM orders
WHERE order_time BETWEEN '2026-08-01 00:00:00'
AND '2026-08-31 23:59:59';如果希望自动计算月份范围,可以使用:
SELECT *
FROM orders
WHERE order_time >= DATE_FORMAT(CURDATE(), '%Y-%m-01')
AND order_time < DATE_ADD(DATE_FORMAT(CURDATE(), '%Y-%m-01'), INTERVAL 1 MONTH);这种写法可以自动获取当前月份第一天,并计算下个月第一天。
不同数据库中的时间函数写法
不同数据库对于时间函数支持有所区别。
MySQL
当前时间:
NOW()当前日期:
CURDATE()增加时间:
DATE_ADD()减少时间:
DATE_SUB()示例:
SELECT *
FROM logs
WHERE create_time BETWEEN DATE_SUB(NOW(), INTERVAL 30 MINUTE)
AND NOW();表示查询最近30分钟的日志。
PostgreSQL
获取当前时间:
CURRENT_TIMESTAMP查询最近7天:
SELECT *
FROM orders
WHERE order_time BETWEEN CURRENT_TIMESTAMP - INTERVAL '7 days'
AND CURRENT_TIMESTAMP;SQL Server
获取当前时间:
GETDATE()查询最近30天:
SELECT *
FROM orders
WHERE order_time BETWEEN DATEADD(DAY,-30,GETDATE())
AND GETDATE();BETWEEN查询中的时间精度问题
时间范围查询最容易出现的问题就是结束时间边界。
例如:
SELECT *
FROM orders
WHERE order_time BETWEEN '2026-08-01'
AND '2026-08-31';如果order_time保存的是:
2026-08-31 15:30:00可能无法匹配,因为结束条件可能被解释为:
2026-08-31 00:00:00更推荐使用左闭右开的方式:
SELECT *
FROM orders
WHERE order_time >= '2026-08-01 00:00:00'
AND order_time < '2026-09-01 00:00:00';这种方式不仅避免时间精度问题,也更适合索引优化。
BETWEEN查询性能优化技巧
避免对时间字段使用函数
不推荐:
SELECT *
FROM orders
WHERE DATE(order_time)='2026-08-25';因为数据库需要对每一行数据执行DATE转换。
推荐:
SELECT *
FROM orders
WHERE order_time >= '2026-08-25 00:00:00'
AND order_time < '2026-08-26 00:00:00';这样数据库可以直接利用时间字段索引。
为时间字段建立索引
对于经常进行范围查询的字段,例如:
创建时间
更新时间
日志时间
交易时间
建议建立索引:
CREATE INDEX idx_order_time
ON orders(order_time);索引能够明显提升大数据量表中的时间范围查询速度。
避免过大的时间扫描范围
例如:
WHERE order_time BETWEEN '2020-01-01'
AND '2026-01-01';如果数据量巨大,可能导致扫描大量记录。
在业务设计中,应尽量限制查询范围,例如按月、按季度查询,或者通过分页方式加载数据。
BETWEEN与时间函数结合的常见应用场景
查询用户最近登录记录
SELECT *
FROM user_login
WHERE login_time BETWEEN DATE_SUB(NOW(),INTERVAL 24 HOUR)
AND NOW();查询当天新增数据
SELECT *
FROM customer
WHERE create_time BETWEEN CURDATE()
AND DATE_ADD(CURDATE(),INTERVAL 1 DAY);查询指定时间段日志
SELECT *
FROM system_log
WHERE log_time BETWEEN '2026-08-25 09:00:00'
AND '2026-08-25 18:00:00';统计最近30天销售额
SELECT SUM(amount)
FROM orders
WHERE order_time BETWEEN DATE_SUB(NOW(),INTERVAL 30 DAY)