2015-02-09 39 views
5

我想獲得最後24小時的數據。我在postgreSQL中寫了一個查詢如下。但我無法按照我的預期得到答案。如何獲得postgreSQL中最後24小時的數據

SELECT startdate::timestamp AS startdate, 
    (DATE_PART('hour',startdate::timestamp)::integer) as hrs,count(guorderid) 
    FROM ord_entitlement 
    WHERE DATE_PART('Day',CURRENT_DATE::timestamp - startdate::timestamp) < 1 
    AND DATE_PART('hour',startdate::timestamp) <= 24 
    GROUP BY hrs,startdate 
    ORDER BY startdate 

回答

3

如果使用CURRENT_DATE,你不會得到的時間,而不是使用now()功能。請嘗試以下操作:

 SELECT startdate::timestamp AS startdate, 
     (DATE_PART('hour',startdate::timestamp)::integer) as hrs,count(guorderid) 
     FROM ord_entitlement 
     WHERE DATE_PART('Day',now() - startdate::timestamptz) < 1 
     GROUP BY hrs,startdate 
     ORDER BY startdate 
+0

當心,一天不一樣24小時。 [有些日子有25或23](https://en.wikipedia.org/wiki/Daylight_saving_time#Procedure)。 – Schwern 2015-02-09 08:58:09

+0

謝謝@Schwern它不適用於夏令時的國家。 – Pirinthan 2015-02-09 09:04:55

+0

@Pirinthan現在也許不會,但事情會改變。斯里蘭卡?在過去的20年中,您的時區已更改三次,其中每個轉換可能會破壞此代碼。 – Schwern 2015-02-09 09:20:59

4

不是檢查日期部分,而是使用時間數學來獲得間隔。使用NOW()獲取時間戳。

SELECT startdate::timestamp AS startdate, 
     (DATE_PART('hour',startdate::timestamp)::integer) as hrs, 
     count(guorderid) 
FROM ord_entitlement 
WHERE NOW() > startdate::timestamptz 
    AND NOW() - startdate::timestamptz <= interval '24 hours' 
GROUP BY hrs,startdate 
ORDER BY startdate 

這可確保無論您的時區或夏令時如何,您都可以獲得最後24小時。 NOW() > startdate::timestamptz確保您不會意外地拿起未來的東西。

+0

DATE_PART不是問題,它是使用NOW()的計算,使得無法首先創建索引。一個函數必須是不可變的,如果你想在你的索引中使用它而NOW()不是。 – 2015-02-09 10:02:06

+0

@FrankHeikens我把一個索引放在時間戳上,並做了一些測試。 PostgreSQL 9.4將在這裏使用該索引幾乎所有的技術。 – Schwern 2015-02-09 10:30:14

+0

@Schwern你可以看到區別[here](http://sqlfiddle.com/#!15/dc9c3/1) - 3條件實際上是相同的,但只有最後一個使用索引。經驗法則是,應該在比較的一邊使用索引表達式/列。 – pozs 2015-02-09 10:43:40

1

date_part()作品等extract(),即它們將extract a subfield從源:

-- they will both yield 9 as result 
select date_part('day', date '2015-01-09') "day part of 2015-01-09", 
     date_part('day', date '2015-02-09') "day part of 2015-02-09"; 

提取day(s)因此不適合於選擇在過去24小時。類似地,提取hour(s)將(幾乎)總是產生小於或等於24

提取day(s)interval(這是減去2 timestamp s的結果)有點不同。其結果可能取決於,區間是否合理,或不:

-- they will both yield 1 as result 
select date_part('day', interval '1 day') "day part of 1 day", 
     date_part('day', interval '1 month 1 day') "day part of 1 month 1 day"; 


-- they will yield 1, 32 and 397 respectively 
select date_part('day', timestamp '2015-02-09' - timestamp '2015-02-08') "interval 1", 
     date_part('day', timestamp '2015-02-09' - timestamp '2015-01-08') "interval 2", 
     date_part('day', timestamp '2015-02-09' - timestamp '2014-01-08') "interval 3"; 

根據事實,時間戳減法沒有給合理的時間間隔是不是最好的選擇,我想。你可以使用簡單的條件,以實現自己的目標:

-- if startdate is a timestamp: 
where current_timestamp - interval '1 day' <= startdate 

-- if startdate is a date: 
where current_date - 1 <= startdate 

如果要禁止將來的日期太(你的問題的標題所暗示的),你可以使用一個單一的between條件:

-- if startdate is a timestamp: 
where startdate between current_timestamp - interval '1 day' and current_timestamp 

-- if startdate is a date: 
where startdate between current_date - 1 and current_date 
+0

如果startdate將來會出現這些問題。 – Schwern 2015-02-09 09:35:30

+0

@Schwern是的,但我沒有看到原始查詢中有任何意圖不允許任何未來的'startdate's。這樣的數據可能不存在,所以在查詢中甚至不提及它可能是安全的。如果它們存在,OP可以使用一個簡單的方法,例如'current_timestamp - interval'1 day'和current_timestamp' – pozs 2015-02-09 09:39:46

+0

@Schwern F.ex.之間的startdate。如果OP有一個只有過去日期(從未來日期)的類似日誌的表,那麼去除未來日期的條件可能意味着更多的傷害而不是幫助。 – pozs 2015-02-09 09:44:13

相關問題