当前位置: 首页 > 面试题库 >

PostgreSQL age()函数:在不同月份登陆时的结果不同/意外

姬银龙
2023-03-14
问题内容

今天,我在运行此查询时在PostgreSQL 9.6中遇到无法解释的结果:

SELECT age('2018-06-30','2018-05-19') AS one,
       age('2018-07-01','2018-05-20') AS two;

两列的预期结果:1 mon 11 days。但是,仅在2018年5月19日至2018年6月30日的时间间隔内,我能达到我的期望,而对于2018年5月20日至2018年7月1日,我将获得更多的一天:1 mon 12 days

我不明白为什么会这样,据我所知,在2018-05-20 2018-07-01之间只是一个间隔,1 mon 11 days这里的Postgres结果是错误的。

我找不到有关PostgreSQLage(timestamp,timestamp)函数的工作原理的任何深入信息。但是,我假设该函数的作用类似于:从月的开始日期开始逐步前进,直到到达月末。从那里转到结束日期。总结几个月和几天。

因此,以我的理解,这就是我的情况(很抱歉,在这里如此冗长,但我觉得有必要):

从2018-05-19开始。向前走一个月。于2018-06-19着陆。N向前走几天直到您到达2018-06-30:

1 day: 20
2 days: 21
3 days: 22
4 days: 23
5 days: 24
6 days: 25
7 days: 26
8 days: 27
9 days: 28
10 days: 29
11 days: 30

= 1 month 11 days.

在2018-05-20和2018-07-01之间的时间应该几乎是相同的:

从2018-05-20开始。向前走一个月。于2018-06-20着陆。N向前走几天直到您到达2018-07-01:

1 day: 21
2 days: 22
3 days: 23
4 days: 24
5 days: 25
6 days: 26
7 days: 27
8 days: 28
9 days: 29
10 days: 30
11 days: 1

= 1 month 11 days.

这是我的错误还是PostgreSQL之一?是否有其他功能/算法以我描述/期望的方式工作?


问题答案:

age由中的timestamptz_age函数计算src/backend/utils/adt/timestamp.c。评论说:

/* timestamptz_age()
 * Calculate time difference while retaining year/month fields.
 * Note that this does not result in an accurate absolute time span
 *  since year and month are out of context once the arithmetic
 *  is done.
 */

该代码首先将参数转换为struct pg_tm变量tm1tm2struct pg_tm类似于C库的struct tm,但具有其他时区字段),然后计算tm每个字段的差值。

在的情况下age('2018-07-01','2018-05-20'),该差异的相关字段如下所示:

tm_mday = -19
tm_mon  =   2
tm_year =   0

现在,负字段已调整。对于tm_mday,代码如下所示:

while (tm->tm_mday < 0)
{
    if (dt1 < dt2)
    {
        tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
        tm->tm_mon--;
    }
    else
    {
        tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
        tm->tm_mon--;
    }
}

由于dt1 > dt2采用else分支,因此代码添加了五月(31)天的天数,并将月份减少了1,最后得出

tm_mday = 12
tm_mon  =  1
tm_year =  0

那就是你得到的结果。

现在乍一看似乎tm2->tm_mon不是选择的正确月份,而最好将左侧参数的前一个月份作为选择:

day_tab[isleap(tm1->tm_year)][(tm1->tm_mon + 10) % 12]

但是我不能说这种选择是否在所有情况下都会更好,并且无论如何注释都会损害该功能,因此我不愿意将其称为错误。

您可能想使用黑客邮件列表。



 类似资料:
  • 问题内容: 以下代码可以在Swift Playground中运行: 这是打印在我的Mac上的结果: 为什么两次打印的结果不同?更有趣的是,当我更改 bbb 的函数签名使其与 aaa相同时 ,两次打印的结果相同。如果在这两个函数调用中使用 全局var 而不是 a.key ,则两次打印的结果是相同的。有谁知道为什么会发生这种奇怪的行为? 问题答案: 为什么两次打印的结果不同? 因为对于每个函数调用,S

  • 有人能向我解释一下为什么当我在Mutate中运行函数时得到的结果与我自己运行它时不同吗?正确的结果是我自己运行它时获得的结果。还有,为什么我会收到这些警告?当我在可变函数中调用时,感觉我可能会将整个列作为参数传递,但我不确定我是否真的了解这里的机制。 创建于 2022-01-06 由 reprex 软件包 (v2.0.1)

  • 为什么在添加相同的数字时输出不同? 输出为: 如果我交换值 我得到的输出为:<代码>15.7000000000001 如何获得相同的输出?

  • 我在这里漏掉了什么?我试过上/下现金,每个字节之间的空格。我不确定还能试什么。 这个问题开始是因为我在Python中实现了这个,但在我担心代码之前,我试图理解为什么这是不同的。

  • 我想将csv文件从一台服务器(Unix服务器A)发送到hdfs目录。根据哪些csv文件,我想将它们放在hdfs中的不同目录中。 我有一个11个csv文件,将由unix服务器A上的kafka制作人发送到kafka。csv文件的第一个元素将包含一个键。我想取第一个元素并使其成为kafka消息的键。此外,我想将数据的值作为kafka中的消息发送。 当它到达kafka集群时,将有一个水槽代理获取数据,并拦

  • 问题内容: 我很难理解scikit-learn和scikit-learn之间的区别(如果有)。 试图预测具有不平衡类的二进制输出(Y = 1时约为1.5%)。 分类器 大鹏曲线 AUC的 和 有人可以解释这种差异吗?我以为两者都只是在计算ROC曲线下的面积。可能是因为数据集不平衡,但我不知道为什么。 谢谢! 问题答案: AUC并不总是在ROC曲线的曲线下方。曲线下面积为下(抽象)地区 的一些 曲线