添加几个月:PostgreSQL与Oracle

时间:2015-02-20 17:53:51

标签: sql oracle postgresql date time

PostgreSQL和Oracle在添加/减去月份/月份之间的行为有所不同。

基本上,如果我们在某一天添加​​1个月,即而不是当月的最后一个,它们都会在结果月份(或最后一个月份)中返回相同的日期如果我们添加的天数更大,则为结果月份,例如2月28日添加到1月31日时。)

的PostgreSQL:

# select '2015-01-12'::timestamptz + '1 month'::interval;
        date        
------------------------
 2015-02-12 00:00:00+03

甲骨文:

> select add_months('12-JAN-2015',1) from dual;    
ADD_MONTH
---------
12-FEB-15

然而

如果我们添加的日期是该月的最后一天,Oracle将返回结果月份的最后一天,即使它更大,PostgreSQL仍会返回相同的日期(或者如果是结果月份更短)。这可能导致一些不一致(甚至有趣!),特别是在多次加/减时甚至分组操作时 - 在PostgreSQL中结果不同:

甲骨文:

> select add_months('28-FEB-2015',1) from dual;
ADD_MONTH
---------
31-MAR-15

> select add_months('31-JAN-2015',4) from dual;

ADD_MONTH
---------
31-MAY-15

> select add_months(add_months(add_months(add_months('31-JAN-2015',1),1),1),1) from dual;

ADD_MONTH
---------
31-MAY-15

的PostgreSQL:

-- Adding 4 months at once:
# select '2015-01-31'::timestamptz + '4
months'::interval;
         date
-------------------------------
2015-05-31 00:00:00+03

-- Adding 4 months by one:
# select '2015-01-31'::timestamptz + '1
months'::interval + '1 months'::interval + '1 months'::interval +'1
months'::interval;
         date
-------------------------------
2015-05-28 00:00:00+03

-- Adding 4 months by one with grouping operations:
# select '2015-01-31'::timestamptz + ('1
months'::interval + '1 months'::interval) + '1 months'::interval +'1
months'::interval;
         date
-------------------------------
2015-05-30 00:00:00+03

-- And even adding 4 months and then subtracting them does not return the initial date!
# select '2015-01-31'::timestamptz + '1 months'::interval + '1 
months'::interval + '1 months'::interval +'1 months'::interval - '4 months'::interval;
        date        
------------------------
 2015-01-28 00:00:00+03

我知道我总是可以使用像

这样的东西
SELECT (date_trunc('MONTH', now())+'1 month'::interval - '1 day'::interval);

获取月份的最后一天并在PostgreSQL中添加月份时使用它,但

问题是:为什么他们都选择实施不同的标准,哪一个更好/更差,为什么。

1 个答案:

答案 0 :(得分:4)

Oracle指定

  

如果日期是该月的最后一天,或者是由此产生的月份   比日期的日期组件少的天数,则结果是最后一天   由此产生的一天。否则,结果在同一天   组件作为日期。

PostgreSQL指定

  

请注意,因年龄而退回的月份可能存在歧义   不同的月份有不同的天数。 PostgreSQL的' S   方法使用两个日期之前的月份   计算部分月份。例如,年龄(' 2004-06-01',   ' 2004-04-30')使用April来产生1个星期一1天,而使用May会   收益率1月2日,因为5月有31天,而4月只有30天。

您可能希望查看PostgreSQL提供的justify_days(interval)函数。

  

为什么他们都选择实施不同的标准,一个是   更好/更差,为什么?

它们都没有比另一个更好(它主要是基于意见的),只是不同。至于为什么他们决定实施不同的标准,说实话,我不认为确实存在理由,可能仅仅是事实。