如何编写单条简洁查询获取近4年每年1-3月的数据
简洁提取指定年份每年1-3月数据的SQL实现方案
核心思路是不要按年份拆分写多组BETWEEN区间判断,通过「限定年份范围+统一限定月份范围」的逻辑,不管覆盖多少个年份,核心判断条件不会冗余变长。
最简洁通用写法(兼容90%以上主流数据库)
用EXTRACT函数分别提取日期的年份、月份做判断,语句不会随目标年份增多而变长:
SELECT * FROM 你的存量数据表 WHERE -- 限定目标年份范围 EXTRACT(YEAR FROM 日期字段名) BETWEEN 2018 AND 2021 -- 统一筛选所有目标年份的1-3月,无需分年重复写区间 AND EXTRACT(MONTH FROM 日期字段名) BETWEEN 1 AND 3;
各数据库简化写法
不同数据库有更简短的日期函数,写法更精简:
- MySQL/MariaDB
SELECT * FROM 你的存量数据表 WHERE YEAR(日期字段名) BETWEEN 2018 AND 2021 AND MONTH(日期字段名) BETWEEN 1 AND 3;
- PostgreSQL
和通用写法完全一致,也支持用DATE_PART函数实现相同逻辑。 - Oracle
SELECT * FROM 你的存量数据表 WHERE TO_CHAR(日期字段名, 'YYYY') BETWEEN '2018' AND '2021' AND TO_NUMBER(TO_CHAR(日期字段名, 'MM')) BETWEEN 1 AND 3;
- SQL Server
SELECT * FROM 你的存量数据表 WHERE YEAR(日期字段名) BETWEEN 2018 AND 2021 AND MONTH(日期字段名) BETWEEN 1 AND 3;
高性能适配写法(适合超大数据量场景)
如果你的表数据量在千万级以上,日期字段建有索引,担心函数运算导致索引失效,可以用区间匹配的写法,同样比重复写BETWEEN更严谨,不会漏带时分秒的时间数据:
SELECT * FROM 你的存量数据表 WHERE (日期字段名 >= '2018-01-01' AND 日期字段名 < '2018-04-01') OR (日期字段名 >= '2019-01-01' AND 日期字段名 < '2019-04-01') OR (日期字段名 >= '2020-01-01' AND 日期字段名 < '2020-04-01') OR (日期字段名 >= '2021-01-01' AND 日期字段名 < '2021-04-01');
注意:不要写
BETWEEN '2018-01-01' AND '2018-03-31'这类条件,如果日期字段是带时分秒的DATETIME/TIMESTAMP类型,会漏掉3月31日0点之后的所有数据,用< 当年4月1日的写法是最严谨的。
两种写法的选择参考:
- 日常数据查询、追求语句简洁易维护,优先选函数提取年月的写法,后续如果要调整年份、月份范围,只需要修改一次数值即可,维护成本极低
- 超大数据量生产环境查询、对响应速度要求高,选明确区间匹配的写法,能100%命中日期字段的索引,查询效率最高
内容的提问来源于stack exchange,提问作者Krishnakumar Prabhu Natarajan
相关产品推荐
相关产品推荐

