我试图在几天内获得差异,将结果转换为十进制:
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转换修改的第一个查询停止工作:
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查询。
答案 0 :(得分:4)
再看看前两个例子。如果你删除外部CAST ... AS DECIMAL你得到
?column?
----------
32872
?column?
------------
32841 days
显然,差异在于“天”。第二个是间隔值而不是简单数字。你只需要这个数字(因为你总是只想要几天)所以你需要提取那个部分。然后你可以投射到你喜欢的任何精度:
SELECT extract(days FROM '32841 days'::interval)::numeric(9,2);
date_part
-----------
32841.00
编辑回应亚历山大的后续行动:
您的第一个示例因相当具体的错误而失败:
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中):
CREATE TEMP TABLE tt AS SELECT
('2909-01-02'::date - '2909-01-01'::date) AS a,
('2909-01-02'::date - '2909-01-02 00:00:00'::timestamp) AS b;
\x
SELECT * FROM tt;
\d tt
这将显示您正在处理的值和类型。重复你认为有用的任意数量的列。
HTH
答案 1 :(得分:1)
如果您正在使用日期进行区间运算,则通常应使用时间戳,如docs中所述。
# SELECT extract(days FROM TO_TIMESTAMP('2999-01-01','yyyy-mm-dd') - TO_TIMESTAMP('2909-01-01','yyyy-mm-dd'))
date_part
-----------
32872
# SELECT extract(days FROM TO_TIMESTAMP('2999-01-01','yyyy-mm-dd') - (TO_TIMESTAMP('2909-01-01','yyyy-mm-dd') + '1 month'::interval) );
date_part
-----------
32841
答案 2 :(得分:0)
向日期添加间隔的结果实际上是时间戳,而不是另一个日期(间隔可能包含时间部分),因此您必须首先将添加的结果转换回日期:
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 )