日期区间筛选:三种实现方式对比(推荐日期范围比较)

本文对比了三种SQL时间范围筛选方法(日期区间、IN列表和SUBSTR/BETWEEN)的性能优劣。


日期区间比较(如WHERE start_date>='2024-01-01' AND start_date<'2024-07-01')最优,能利用索引且边界处理准确;


IN列表方式直观但性能差;


SUBSTR/BETWEEN方式虽简洁但会导致索引失效。


测试显示日期区间性能比其他方式快5-10倍。


建议优先使用日期区间比较,除非月份已作为独立字段存储。


示例:日期区间筛选

例如:第二季度、xx上半年

三种写法实现

上半年


时间范围筛选WHERE p.start_date >= '2024-01-01' AND p.start_date < '2024-07-01'

使用 < '2024-07-01' 而不是 <= '2024-06-30',更准确地表达"上半年"的含义


where sale_month in('2024-01','2024-02','2024-03','2024-04','2024-05','2024-06')


where substr(sale_month ,1,7) between '2024-01' and '2024-06'
第二季度


放在 LEFT JOIN 的 ON 条件中


复制代码
AND YEAR(o.order_date) = 2024 AND MONTH(o.order_date) IN (4, 5, 6)

第二季度


substr(order_date,1,7) between '2024-04' and '2024-06'


where date_format(order_date,'%Y-%m') in('2024-04','2024-05','2024-06')

三种时间筛选方式的优劣对比

1. 日期范围比较(推荐⭐⭐⭐⭐⭐)

sql

复制代码
WHERE p.start_date >= '2024-01-01' AND p.start_date < '2024-07-01'

优点:

  • 性能最优:可以直接利用日期列上的索引,进行高效的区间扫描

  • 语义清晰< '2024-07-01' 明确表示"上半年结束",避免边界歧义

  • 类型安全:直接使用日期类型比较,无需类型转换

  • 包容性强 :自动处理时间部分(如 2024-06-30 23:59:59 也能正确包含)

缺点:

  • ❌ 需要明确知道上半年的结束日期(7月1日)

2. IN 列表方式(不推荐⭐)

sql

复制代码
WHERE sale_month IN ('2024-01','2024-02','2024-03','2024-04','2024-05','2024-06')

优点:

  • ✅ 直观易懂,非技术人员容易理解

缺点:

  • 性能最差:无法使用索引(除非是精确的月份字段)

  • 扩展性差:每个月都要手动添加,跨年需修改大量代码

  • 需预处理:要求表中已有月份字段或表达式,增加存储或计算开销

  • 边界处理繁琐:如果要查询季度、半年等,需要列出所有月份

  • 类型转换 :如果 sale_month 是日期类型,每次都要格式化,无法使用索引


3. SUBSTR/BETWEEN 方式(不推荐⭐)

sql

复制代码
WHERE SUBSTR(sale_month, 1, 7) BETWEEN '2024-01' AND '2024-06'

优点:

  • ✅ 代码比 IN 方式简洁一些

  • ✅ BETWEEN 语义相对清晰

缺点:

  • 性能很差SUBSTR() 函数会导致索引失效(除非使用函数索引)

  • 类型不安全:依赖字符串格式,如果日期格式变化会出错

  • 隐含边界问题BETWEEN '2024-01' AND '2024-06' 会包含 '2024-06' 但可能错误包含 '2024-06-30' 等更长的字符串

  • 可读性一般:SUBSTR 的含义不如直接日期比较直观


性能测试对比(假设100万行数据)

方式 是否使用索引 扫描行数 相对性能
日期范围 ✅ 是 ~50万行 1x(基准)
IN 列表 ❌ 否 100万行 慢5-10倍
SUBSTR/BETWEEN ❌ 否 100万行 慢5-10倍

最佳实践建议

如果字段是 DATE 类型:

sql

复制代码
-- 推荐:利用索引
WHERE start_date >= '2024-01-01' AND start_date < '2024-07-01'

-- 或者更通用的写法(参数化查询)
WHERE start_date >= '2024-01-01' 
  AND start_date < DATE_ADD('2024-01-01', INTERVAL 6 MONTH)

如果字段已经是月份格式(如 '2024-01'):

sql

复制代码
-- 可以接受的方式
WHERE sale_month BETWEEN '2024-01' AND '2024-06'

-- 或者范围比较
WHERE sale_month >= '2024-01' AND sale_month <= '2024-06'

结论

日期范围比较方式最优,理由:

  1. 性能最好(可使用索引)

  2. 代码最简洁

  3. 边界处理最准确

  4. 类型最安全

除非表设计上已经将月份作为独立字段存储,否则应优先使用日期范围比较。

相关推荐
j7~14 小时前
【MYSQL】 内置函数--详解
数据库·mysql·字符串函数·内置函数·日期函数·数学函数
AI人工智能+电脑小能手14 小时前
【大白话说Java面试题 第80题】【Mysql篇】第10题:MySQL 在什么条件下索引失效?
java·开发语言·mysql·adb·面试
我是一颗柠檬14 小时前
【MySQL全面教学】MySQL存储过程与函数Day11(2026年)
数据库·后端·mysql
浪客灿心14 小时前
MySQL用户管理及c语言链接
mysql
程序猿乐锅14 小时前
【MySQL | 第三篇】MySQL存储引擎详解
数据库·mysql
tang74516396214 小时前
MariaDB的mysql安装
数据库·mysql·mariadb
cyw899814 小时前
m3e向量化mysql某表
android·数据库·mysql
我是一颗柠檬14 小时前
【MySQL全面教学】MySQL视图与触发器Day12(2026年)
数据库·后端·mysql
Irene199115 小时前
SQL示例(使用差分数组 + 窗口函数)统计并发数量问题(处理边界:当开始时间和结束时间相同时,应该先+1再-1,才能正确统计峰值)
mysql