0

我有一個基於CTE的查詢,其中我檢索兩個給定時間間隔之間的小時間隔。我的查詢工作如下:當時間戳的開始時間大於時間戳的結束時間時查詢失敗

獲取開始和結束日期時間(比如說07-13-2011 00:21:09和07-31-2011 21:11:21)獲得每小時間隔的小時總查詢值(在這裏是00到21,總共21小時,但這是參數化的,取決於我爲輸入提供的時間)。

此查詢適用於第一個時間戳的小時小於第二個時間的輸入 - 例如, 03 AM是第一個時間戳的時間,07 AM是第二個時間戳的時間,但是存在問題。當我想要檢索輸入的總計數時,如07-13-2011 22:11:43和07-25-2011 04:06:04,我遇到了問題。我需要檢索以下查詢的總計數:

07-13-2011 22:00:00 143 //representing the total amounts of queries 22:11:43 - 22:59:59 interval- 
07-13-2011 23:00:00 121 //representing the total amounts of queries in 23:00:00 -23:59:59 interval- 
07-14-2011 00:00:00  65 //00:00:00 - 00:59:59 interval 
07-14-2011 01:00:00  51 //01:00:00 - 01:59:59 interval... 
. 
. 
. 
07-14-2011 04:00:00 22 //query amount for 04:00:00 - 04:06:04 interval 

等等。除了我在下面寫的CTE查詢外,還需要做些什麼?

WITH cal AS (
    SELECT generate_series('2011-02-02 00:00:00'::timestamp 
         , '2012-04-01 05:00:00'::timestamp 
         , '1 hour'::interval) AS stamp 
    ) 
, qqq AS (
    SELECT date_trunc('hour', calltime) AS stamp 
    , count(*) AS zcount 
    FROM mytable 
    WHERE calltime >= '07-13-2011 22:00:00' 
    AND calltime <='07-31-2011 04:33:21' 
    AND calltime::time >= '22:00:00' 
    AND calltime::time <= '04:33:21' 
    -- this calltime::time part obviously doesn't work due to common sense and logic 
    -- edited it to show what I try to mean 
    AND date_part('hour', calltime) >= 0 
    AND date_part('hour', calltime) <= 21 
    GROUP BY date_trunc('hour', calltime) 
    ) 
SELECT cal.stamp 
    , COALESCE (qqq.zcount, 0) AS zcount 
FROM cal 
LEFT JOIN qqq ON cal.stamp = qqq.stamp 
WHERE cal.stamp >= '07-13-2011 22:00:00' 
AND cal.stamp<='07-31-2011 04:33:21' 
AND date_part('hour', cal.stamp) >= 0 
AND date_part('hour', cal.stamp) <= 21 
ORDER BY stamp ASC; 
+0

文本和示例在幾個細節上相互矛盾(例如:是否要將結果中的小時數限制爲「0-21」?)。我爲我的答案選擇了* one *解釋並添加了可選的註釋子句。 – 2012-08-15 12:35:57

+0

@ErwinBrandstetter是的,我應該解決這個問題。我想限制小時數作爲用戶輸入的時間間隔 - 這是在caltime和cal.stamp之間的calltime中給出的時間戳,在我的例子中是一天的22:00:00和另一天的04:32:21,在該時間間隔(包括輸入日期)內的所有日子將顯示22到04:32等部分之間的每小時查詢計數。 – sm90901 2012-08-15 12:41:42

+0

這仍然不明確:「在該時間間隔內的所有日子(包括輸入日期)將顯示22到04:32等部分之間的小時查詢計數。」嘗試清楚!你真的想在第一天包括00:00 - 04:32嗎? – 2012-08-15 13:24:18

回答

2

考慮這個修正版:

WITH param AS (
    SELECT '2011-07-13 22:11:43'::timestamp AS start -- supply start/stop once 
     ,'2011-07-25 04:06:04'::timestamp AS stop 
    ) 
    , cal AS (
    SELECT generate_series(date_trunc('hour', p.start) 
         ,date_trunc('hour', p.stop + interval '1h') 
         ,interval '1h') AS h 
    FROM param p 
    ) 
    , q AS (
    SELECT date_trunc('hour', calltime) AS h 
     ,count(*) AS ct 
    FROM mytable 
     ,param p 
    WHERE calltime >= p.start 
    AND calltime <= p.stop 
    -- uncomment if you actually want to exclude hours 22 & 23 (?) 
    -- AND extract('hour' FROM calltime) BETWEEN 0 AND 21 
    GROUP BY 1 
    ) 
SELECT cal.h, COALESCE(q.ct, 0) AS ct 
FROM cal 
LEFT JOIN q USING (h) 
-- uncomment if you actually want to exclude hours 22 & 23 (?) 
-- WHERE extract('hour' FROM cal.h) BETWEEN 0 AND 21 
ORDER BY 1; 

主要的變化是從生成的實際時間跨度小時的時候了。
刪除了一些不需要的條件。
對時間戳使用ISO 8601格式(適用於每種語言環境)。

查找更多的上下文和鏈接在這個related answer。唯一的區別是:在那裏它的運行計數。

1

這一條款:

AND calltime::time >= '00:21:09' AND calltime::time <= '21:11:21' 

看起來可疑,考慮到其他條款。

目前尚不清楚爲什麼需要它,並且如果文字時間分別爲22:11:4304:06:04作爲示例不起作用,則該條款將過濾掉所有內容,以便每小時結束0次計數。

+0

我的不好,編輯錯誤。 – sm90901 2012-08-15 12:57:23