【问题标题】:Why is result of age() not always equivalent to interval when going back in time?为什么年龄()的结果在时间倒退时并不总是等于时间间隔?
【发布时间】:2018-06-04 07:34:27
【问题描述】:

我在 PostgreSQL 9.6 转弯日期计算中遇到了我的 SQL 代码的一些意外行为。在分析时,我发现 Postgres 不会总是返回相同的值返回 n 天,然后使用 age() 计算持续时间。

考虑这段代码:我们将某一天设置为“基数”,返回 45 天,然后计算持续时间。

WITH basedate AS (SELECT '2018-05-01'::date AS b), 
     myperiod AS (SELECT (basedate.b - interval '45 days') AS "startDate",
     basedate.b AS "endDate" FROM basedate)
SELECT age("endDate","startDate") FROM myperiod;

我希望这个查询总是得到45 days。但是,如果我将basedate 更改为2018-06-01,我将得到44 days

为什么会这样?

我的猜测是,这与 May 有 31 天有关。但是,我无法准确解释原因,因为如果我将 45 days 更改为 15 days2018-05-012018-06-01 将导致相同的持续时间。

【问题讨论】:

标签: sql postgresql datetime


【解决方案1】:

这并不完全正确。

您的第一个查询返回

      age      
---------------
 1 mon 15 days
(1 row)

如果你将日期修改为2018-06-01,你会得到

      age      
---------------
 1 mon 14 days
(1 row)

两个都是对的,不是吗?

问题在于 PostgreSQL 在 justify_interval 之类的函数中将一个月视为 30 天:

SELECT justify_interval('45 days');

 justify_interval 
------------------
 1 mon 15 days
(1 row)

但是,另一种方法是抛出错误,并且该行为被清楚地记录在案。

【讨论】:

    【解决方案2】:

    Laurenz Albe 的回答指出了正确的事情:我应该预料到一个以1 mon 开头的结果。

    问题实际上出在客户端,在本例中是 OmniDB 2.8。请参阅此处:GitHub OmniDB: Does OmniDB auto-convert intervals to days? 该问题已在 OmniDB 2.9 中修复

    在我测试过的所有其他客户端中,我得到了 Laurenz Albe 预测的结果。

    因此,如果您在遇到类似问题时遇到这里:无论如何,请检查问题是否出在您的客户端或您使用的库中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-18
      • 2021-08-20
      相关资源
      最近更新 更多