如何用SQL获取两个指定日期间所有月份的最后一天?现有写法是否可优化
你目前使用的方案依赖系统表ALL_OBJECTS,存在两个明显缺陷:
- 若两个日期间隔过久,超出
ALL_OBJECTS的总行数时会返回不全的结果 - 需要额外的
DISTINCT去重,浪费计算资源
优化方案1(适用Oracle 11gR2及以上版本,逻辑最清晰)
使用递归CTE生成所需月份的最后一天,无需依赖系统表、无需去重:
WITH month_ends AS ( -- 取起始日期所在月的最后一天作为初始值 SELECT LAST_DAY(TO_DATE('2014-08-15', 'YYYY-MM-DD')) AS month_end FROM dual UNION ALL -- 每次递归加1个月,直到新生成的日期超过结束日期 SELECT ADD_MONTHS(month_end, 1) FROM month_ends WHERE ADD_MONTHS(month_end, 1) < TO_DATE('2014-10-15', 'YYYY-MM-DD') ) SELECT month_end FROM month_ends;
优化方案2(兼容Oracle所有版本,性能最优)
使用CONNECT BY层级查询实现,代码更简洁:
SELECT LAST_DAY(ADD_MONTHS(TO_DATE('2014-08-15', 'YYYY-MM-DD'), LEVEL - 1)) AS month_end FROM dual CONNECT BY ADD_MONTHS(TO_DATE('2014-08-15', 'YYYY-MM-DD'), LEVEL - 1) < TO_DATE('2014-10-15', 'YYYY-MM-DD');
两种方案输出都完全符合预期:
2014-08-31 2014-09-30
内容的提问来源于stack exchange,提问作者thequestionasker
相关产品推荐
相关产品推荐

