SQL中BETWEEN操作符与时间函数结合实现时间范围查询

0 次阅读

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:

字段类型
idint
user_idint
order_timedatetime
amountdecimal

如果需要查询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)