sql - 添加月份至今 : PostgreSQL vs. Oracle

标签 sql oracle postgresql date time

PostgreSQL 和 Oracle 在日期上加/减月份的行为不同。

基本上,如果我们将 1 个月加到某一天,而这不是该月的最后一天,它们将在结果月份(或最后一个如果我们添加的天数更大,则为结果月份,例如,添加到 1 月 31 日时为 2 月 28 日)。

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 中添加月份时使用它,但是

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

最佳答案

甲骨文指定

If date is the last day of the month or if the resulting month has fewer days than the day component of date, then the result is the last day of the resulting month. Otherwise, the result has the same day component as date.

PostgreSQL 指定

Note there can be ambiguity in the months returned by age because different months have a different number of days. PostgreSQL's approach uses the month from the earlier of the two dates when calculating partial months. For example, age('2004-06-01', '2004-04-30') uses April to yield 1 mon 1 day, while using May would yield 1 mon 2 days because May has 31 days, while April has only 30.

您可能想看看 PostgreSQL 提供的 justify_days(interval) 函数。

why both of them chose to implement different standards, which one is better/worse and why ?

没有一个比另一个更好(主要是基于意见),只是不同而已。至于为什么他们决定实现不同的标准,老实说我不认为真的有原因,可能只是一个事实问题。

关于sql - 添加月份至今 : PostgreSQL vs. Oracle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28635226/

相关文章:

ruby-on-rails - 保存失败后 Rails 不回滚事务()

sql - 生成加密安全 ID 而不是顺序身份/自动递增

php - 使用 PHP 更新数据库中的图像

sql - MS Access 中的条件默认值

sql - 在Oracle中将行动态转换为列

java - 如何在 Oracle 11 中使用 JDBC 4 驱动程序?

oracle - SYS_CONNECT_BY_PATH 和 START WITH/CONNECT BY PostgreSQL 等效项

sql - Postgres 列的任意字符串名称

sql - Postgresql 在多个连接上返回重复数据

json - 格式 JSON Postgresql