Postgresql。日期间隔问题

Postgresql。日期间隔问题,postgresql,sqldatatypes,Postgresql,Sqldatatypes,我尝试以天为单位计算差异,将结果转换为十进制: SELECT CAST( TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd') AS DECIMAL ) ; 现在,如果我在第二天加上1个月: SELECT CAST( TO_DATE('2999-01-01','yyyy-mm-dd') - (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' *

我尝试以天为单位计算差异,将结果转换为十进制:

SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd') AS DECIMAL )
;
现在,如果我在第二天加上1个月:

SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd') - (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ) AS DECIMAL )
;
我得到一个错误: 错误:无法将类型间隔转换为数字

好的,我可以强制转换为char以获得结果:

SELECT
CAST( TO_CHAR( TO_DATE('2909-02-10','yyyy-mm-dd') - (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ), 'DD') AS DECIMAL )
;
但在这种情况下,使用TO_CHAR casting修改的第一个查询将停止工作:

SELECT
CAST( TO_CHAR(TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'), 'DD') AS DECIMAL )
;
我得到错误:多个小数点。


所以,我的问题是,如何使用相同的sql语句获得天数?对于这两个sql查询。

请再次查看前两个示例。如果你移除外部铸件。。。就像你得到的那样

 ?column? 
----------
    32872

  ?column?  
------------
 32841 days
显然,区别在于“天”。第二个是区间值,而不是简单的数字。您只需要数字(因为您总是只需要天数),因此需要提取该部分。然后,您可以按自己喜欢的精度进行投射:

SELECT extract(days FROM '32841 days'::interval)::numeric(9,2);
 date_part 
-----------
  32841.00

编辑对Alexandr后续行动的回应:

您的第一个示例失败,出现了一个相当具体的错误:

SELECT extract(days FROM (TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'))::interval)::numeric(9,2);

ERROR:  cannot cast type integer to interval
LINE 1: ...yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'))::interval...
这里您得到了一个整数(这是您最初想要的),并尝试将其转换为一个间隔(出于我不理解的原因)。它抱怨它不知道你想要什么单位。你想要32872秒,几小时,几周,几个世纪

第二个例子是抱怨,因为您试图从一个简单的整数中提取“day”部分,当然,系统中没有extract()函数来完成这项工作

我认为您可能需要退一步,花点时间理解各种表达式返回的值

将一个日期与另一个日期相减,可以得到分隔日期的天数——作为一个整数。实际上,没有其他明智的措施

在日期上加(或减)一个间隔会给你一个时间戳(没有时区),因为间隔可能包含整天、天、小时、秒等

从日期中减去时间戳将得到一个间隔,因为结果可能包含天、小时、秒等

如果您有一个时间间隔,并且只需要天数部分,那么您可以对其使用extract(),并返回整数天数

如果要转换为数值而不是间隔,则需要整数(或浮点)天数,因为如果没有单位,将间隔转换为标量是没有意义的

所以-要么坚持日期和日期算法(简单),要么意识到你在使用时间戳(灵活),但要了解它是什么

要了解正在发生的事情,可以执行以下操作(在psql中):

这将显示您正在处理的值和类型。重复以上步骤,尽可能多地选择有用的列


HTH

再看一下前两个例子。如果你移除外部铸件。。。就像你得到的那样

 ?column? 
----------
    32872

  ?column?  
------------
 32841 days
显然,区别在于“天”。第二个是区间值,而不是简单的数字。您只需要数字(因为您总是只需要天数),因此需要提取该部分。然后,您可以按自己喜欢的精度进行投射:

SELECT extract(days FROM '32841 days'::interval)::numeric(9,2);
 date_part 
-----------
  32841.00

编辑对Alexandr后续行动的回应:

您的第一个示例失败,出现了一个相当具体的错误:

SELECT extract(days FROM (TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'))::interval)::numeric(9,2);

ERROR:  cannot cast type integer to interval
LINE 1: ...yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'))::interval...
这里您得到了一个整数(这是您最初想要的),并尝试将其转换为一个间隔(出于我不理解的原因)。它抱怨它不知道你想要什么单位。你想要32872秒,几小时,几周,几个世纪

第二个例子是抱怨,因为您试图从一个简单的整数中提取“day”部分,当然,系统中没有extract()函数来完成这项工作

我认为您可能需要退一步,花点时间理解各种表达式返回的值

将一个日期与另一个日期相减,可以得到分隔日期的天数——作为一个整数。实际上,没有其他明智的措施

在日期上加(或减)一个间隔会给你一个时间戳(没有时区),因为间隔可能包含整天、天、小时、秒等

从日期中减去时间戳将得到一个间隔,因为结果可能包含天、小时、秒等

如果您有一个时间间隔,并且只需要天数部分,那么您可以对其使用extract(),并返回整数天数

如果要转换为数值而不是间隔,则需要整数(或浮点)天数,因为如果没有单位,将间隔转换为标量是没有意义的

所以-要么坚持日期和日期算法(简单),要么意识到你在使用时间戳(灵活),但要了解它是什么

要了解正在发生的事情,可以执行以下操作(在psql中):

这将显示您正在处理的值和类型。重复以上步骤,尽可能多地选择有用的列


HTH

向日期添加间隔的结果实际上是一个时间戳,而不是另一个日期(间隔可能包含时间部分),因此您必须首先将添加的结果转换回日期:

SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd')
       - CAST( (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ) AS DATE)
      AS DECIMAL )

向日期添加间隔的结果实际上是一个时间戳,而不是另一个日期(间隔可能包含时间部分),因此您必须首先将添加的结果向下转换为日期:

SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd')
       - CAST( (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ) AS DATE)
      AS DECIMAL )

如果要对日期进行间隔运算,通常应该使用时间戳,如中所述


如果要对日期进行间隔运算,通常应该使用时间戳,如中所述


如何将“extract”与表字段或TO_DATE语句一起使用?以下选项不起作用:选择提取(从(截止日期('2999-01-01','yyyy-mm-dd')到截止日期('2909-01-01','yyyy-mm-dd')的天数)::间隔::数字(9,2);选择摘录(从(截止日期('2999-01-01','yyyy-mm-dd')-截止日期('2909-01-01','yyyy-mm-dd')起的天数):数字(9,2);非常感谢您如此详细的回复!如何将“extract”与表字段一起使用,或者如何使用