2012-12-11 155 views
0

我試圖讓日差,鑄造結果爲十進制:Postgresql。日期間隔問題

SELECT 
CAST(TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd') AS DECIMAL) 
; 

現在,如果我1個月添加到第2日:

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

我得到的錯誤: 錯誤:無法投類型間隔數字

OK,我可以投到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查詢。

回答

2

再看看你的前兩個例子。如果您刪除外部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 什麼在你的間隔 - 秒,幾小時,幾周,幾個世紀?

第二個例子是抱怨,因爲你試圖從一個簡單的整數中提取「日」部分,當然系統中沒有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

+0

如何在表格字段或TO_DATE語句中使用'extract'?以下幾個不起作用:SELECT extract(days FROM(TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd') )::間隔)::數字(9,2); (日期FROM(TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'))):: numeric( 9,2); – Alexandr

+0

非常感謝您的詳細回覆! – Alexandr

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) 
0

如果你正在做的日期區間算術,你一般應使用時間戳來代替,如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