为啥 Oracle ADD_MONTHS() 返回的 sysdate 值与我硬编码今天的日期不同?

Posted

技术标签:

【中文标题】为啥 Oracle ADD_MONTHS() 返回的 sysdate 值与我硬编码今天的日期不同?【英文标题】:Why is Oracle ADD_MONTHS() returning a different value for sysdate than if I hardcode today's date?为什么 Oracle ADD_MONTHS() 返回的 sysdate 值与我硬编码今天的日期不同? 【发布时间】:2021-09-02 19:47:36 【问题描述】:

我需要提取 6 个月前到现在的所有记录。

起初我硬编码了今天(2021 年 9 月 2 日)的日期并得到了我预期的结果:

select case_no, closed_dt from table1
where closed_dt >= add_months(TO_DATE('09/02/2021', 'mm/dd/yyyy'), -6)
order by closed_dt

这给了我想要的结果,从 2021 年 3 月 2 日到今天的记录列表:

CASE_NO | CLOSED_DT
-------------------
     94 | 03/02/2021
     57 | 03/03/2021
     29 | 07/26/2021
     04 | 09/02/2021

但是,此查询将在自动脚本中,因此我无法对日期进行硬编码,我需要将其动态更改为始终为过去 6 个月。所以我尝试使用 sysdate,得到了这个结果:

select case_no, closed_dt from table1
where closed_dt >= add_months(sysdate, -6)
order by closed_dt

结果:

CASE_NO | CLOSED_DT
-------------------
     57 | 03/03/2021
     29 | 07/26/2021
     04 | 09/02/2021

如您所见,3 月 2 日的记录现在没有返回,即使它应该返回。

更令人困惑的是,当我这样做时

select add_months(sysdate, -6) from dual

它按预期返回03/02/2021

谁能解释发生了什么,并提供正确的解决方案来使用 sysdate 返回 6 个月前的记录?

【问题讨论】:

一个明显的原因是时区问题。 一个更明显的原因是sysdate 有一个(通常非零)时间组件。您的硬编码相当于在调用add_months() 时使用trunc(sysdate),而不是sysdate 您能否解释一下,当我从 dual 中选择 sysdate 时,如何使 sysdate 看起来正确,但在更复杂的查询中却无法正常工作? @mathguy 我尝试使用 trunc(sysdate) 进行查询,现在它可以按预期工作。感谢您的意见。请把它放在答案中,这样我就可以投票了。 【参考方案1】:

Oracle date 始终具有日期和时间组件。 TO_DATE('09/02/2021', 'mm/dd/yyyy') 返回 2021 年 9 月 2 日午夜的日期。另一方面,sysdate 返回当前日期和时间(我的本地计算机上的 2021 年 9 月 2 日 13:51:00)。假设您的表中的数据值是 2021 年 3 月 2 日午夜,那么第一个查询将返回该行,而第二个查询则不会因为时间原因。

我希望您想使用 trunc 函数将时间组件设置为午夜

where closed_dt >= add_months(trunc(sysdate), -6)

【讨论】:

以上是关于为啥 Oracle ADD_MONTHS() 返回的 sysdate 值与我硬编码今天的日期不同?的主要内容,如果未能解决你的问题,请参考以下文章

mysql里有没有类似oracle里的ADD_MONTHS函数,自能的提取间隔的月份

oracle时间函数

Oracle中add_months()函数的用法

ORACLE 时间处理

oracle 日期常用函数 (ADD_MONTHS,LAST_DAY,NEXT_DAY,MONTHS_BETWEEN,NEW_TIME,ROUND,TRUNC)

oracle sql 获取本季度所有月份,上季度所有月份