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

本文对比了三种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. 类型最安全

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

相关推荐
小猿姐8 小时前
MySQL Top 10 热点问题 AI 运维实战:从内核诊断到云原生运维
mysql·云原生·aiops
云技纵横19 小时前
Gap Lock 死锁实战:5 秒在本地复现 MySQL 间隙锁死锁
后端·mysql
无响应de神19 小时前
三、用户与权限管理
数据库·mysql
摇滚侠1 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
ApacheSeaTunnel2 天前
实战演示 | 基于 Apache SeaTunnel 与 Apache DolphinScheduler 实现 MySQL 到 Doris 离线定时增量同步
大数据·mysql·开源·doris·数据集成·seatunnel·数据同步
DARLING Zero two♡2 天前
【MySQL数据库】数据类型与表约束
数据库·mysql
活宝小娜2 天前
mysql详细安装教程
数据库·mysql·adb
Database_Cool_2 天前
什么是数据仓库物化视图?AnalyticDB MySQL 实时物化视图能力解析
人工智能·mysql·阿里云
Database_Cool_2 天前
即席查询(Ad-Hoc)数据库选型:AnalyticDB MySQL 秒级 Ad-Hoc 分析方案
数据库·mysql