Oracle SQL查询最近3个完整自然月数据的正确写法
问题说明
需要查询最近3个完整自然月的数据,以当前时间处于6月为例,需覆盖3月、4月、5月全月数据,即时间范围为3月1日至5月31日。现有SQL过滤条件会错误包含6月1日的多余数据,原语句如下:
where d.D_DATE between add_months(trunc(sysdate, 'month'), -3) and add_months(trunc(sysdate, 'month'),0)
错误原因
原写法的问题出在区间规则和边界值选择上:
between是双侧闭区间判断,等价于D_DATE >= 左边界 and D_DATE <= 右边界- 原语句右边界
add_months(trunc(sysdate, 'month'),0)的计算结果是当月1日0点,判断条件会把D_DATE等于当月1日0点的记录(即6月1日的纯日期数据)纳入结果,产生多余数据 - 如果为了修复问题直接把右边界改成上月最后一天(比如
add_months(last_day(sysdate), -1)),一旦D_DATE是带时分秒、毫秒的时间戳类型,会漏掉上月最后一天0点到24点之间的部分数据,兼容性很差
正确调整方案
使用左闭右开的区间判断,这种写法对纯日期、带精度的时间戳类型都兼容,不会出现多算、漏算问题:
where d.D_DATE >= add_months(trunc(sysdate, 'month'), -3) and d.D_DATE < trunc(sysdate, 'month')
逻辑验证
以当前时间在6月为例验证匹配范围:
- 左边界计算值为3月1日0点,右边界计算值为6月1日0点
- 判断规则为「日期大于等于3月1日0点,且小于6月1日0点」,刚好完整覆盖3、4、5月全量数据,既不会包含6月任何记录,也不会漏掉5月31日任意时刻的有效数据
内容的提问来源于stack exchange,提问作者python_enthusiast90
相关产品推荐
相关产品推荐

