0

2 つの指定された期間の間の 1 時間ごとの間隔を取得する CTE ベースのクエリがあります。私のクエリは次のように機能します:

開始日時と終了日時を取得すると (2011 年 7 月 13 日 00:21:09 と 2011 年 7 月 31 日 21:11:21 としましょう)、1 時間ごとの合計クエリ値が取得されます (ここでは 00 から 21 です)。合計 21 時間ですが、これはパラメトリックであり、入力に与えた時間によって異なります)。

このクエリは、最初のタイムスタンプの時間が 2 番目のタイムスタンプよりも小さい入力に対してはうまく機能します。たとえば、最初のタイムスタンプの時間は 03 AM、2 番目のタイムスタンプの時間は 07 AM ですが、問題があります。2011 年 7 月 13 日 22:11:43 や 2011 年 7 月 25 日 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;
4

2 に答える 2

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 形式を使用します (これはすべてのロケールで機能します)。

この関連する回答で、より多くのコンテキストとリンクを見つけてください。唯一の違いは、そこにあるのはランニングカウントに関するものです。

于 2012-08-15T12:12:55.617 に答える
1

この条項:

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

他の条項を考えると、疑わしいように見えます。

なぜそれが必要なのかは明らかではありません。また、例として与えられた文字どおりの時間が22:11:43機能04:06:04しない場合、この句はすべてを除外するため、1 時間ごとにカウントが 0 になります。

于 2012-08-15T12:24:29.520 に答える