1

CTEベースのクエリがあり、指定された2つのタイムスタンプ間のユーザーリクエストの合計量を取得し、2つの日付の間の1時間に行われたリクエストの数を示しています。私のクエリは次のように機能します。

1)開始日時と終了日時を取得する(たとえば、2011年7月13日10:21:09および2011年7月31日15:11:21)

2)指定されたタイムスタンプの1時間-1時間間隔でリクエストの量を取得します。(上記のように、開始タイムスタンプの時間が10で、終了タイムスタンプの時間が15の場合、7月13日から31日までの毎日の10、11、12、13、14、15時間のリクエストの1時間あたりの量を表示する必要があります)

クエリは次のようになります。

WITH cal AS (
    SELECT generate_series('2-2-2011 00:00:00'::timestamp , '1-4-2012 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 >= '13-7-2011 10:21:09' 
          AND calltime <= '31-7-2011 15:11:21' AND calltime::time >= '10:00:00' AND
          calltime::time <= '15:59:59' AND date_part('hour', calltime) >= 8 AND 
          date_part('hour', calltime) <= 15
 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 >= '13-7-2011 10:00:00' AND cal.stamp <= '31-7-2011 15:11:21' 
       AND date_part('hour', cal.stamp) >= 10 AND 
       date_part('hour', cal.stamp) <= 15
ORDER BY stamp ASC;

このクエリは、10〜15時間のリクエストの量が1時間間隔で表示されることを示しています(10:21:09〜11:00のXリクエスト、11:00〜11:59のYリクエスト、12:00〜12のZリクエスト:59 ...、Pリクエスト15:00〜15:11:21)7月13日午前10時から午後3時まで、7月31日午前10時から午後3時までの毎日

これは、最初のタイムスタンプの時間値が2番目のタイムスタンプの時間値よりも小さい入力(ここでは、最初のタイムスタンプの時間は10、2番目のタイムスタンプの時間は15)でうまく機能しますが、問題があります。これを07-13-20112:11:43や07-31-201104:06:04などの入力に適用したい場合は、1時間あたりのリクエスト数を22から04の間で取得します。ある日、クエリの構造が原因で問題が発生している可能性があります。次のようなリクエストの総数を取得する必要があります。

    stamp                 zcount
    "2011-07-13 22:00:00"  123
    "2011-07-13 23:00:00"  338
    "2011-07-14 00:00:00"  184
    "2011-07-13 01:00:00"  298
    "2011-07-13 02:00:00"  162
    "2011-07-13 03:00:00"  293
    "2011-07-14 04:00:00"  216
    "2011-07-14 22:00:00"  392
    "2011-07-14 23:00:00"  268
    "2011-07-15 00:00:00"  483
    "2011-07-15 01:00:00"  327
    "2011-07-15 02:00:00"  419
    "2011-07-15 03:00:00"  121
    "2011-07-15 04:00:00"  231
     .
     . 
    "2011-07-30 22:00:00"  392
    "2011-07-30 23:00:00"  268
    "2011-07-31 00:00:00"  483
    "2011-07-31 01:00:00"  327
    "2011-07-31 02:00:00"  419
    "2011-07-31 03:00:00"  544
    "2011-07-31 04:00:00"  231

2番目のタイムスタンプの時間値が最初のタイムスタンプの時間値よりも小さい場合(たとえば、最初のタイムスタンプの場合は22、2番目のタイムスタンプの場合は4)で確実に機能するようにするには、クエリで何を変更する必要がありますか?私は現在これの回避策を使用していますが、それはあまりエレガントではないので、それを変更したいと思います。

4

1 に答える 1

4

正直に言います。近くにいるのかわからない。

外部クエリのwhere句で繰り返されるため、qqqのWHERE句からほとんどのものを削除しました。また、ISOタイムスタンプに切り替えました。これは、ISOタイムスタンプが非常に読みやすいためです。

おそらく、これを引数を渡すことができる関数として書き直したいと思うでしょう。

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 >= '2011-07-13 20:21:09' 
    AND calltime <= '2011-07-31 15:11: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 >= '2011-07-13 20:00:00' 
  AND cal.stamp <= '2011-07-31 15:11:21' 
  AND (
    extract ('hour' from cal.stamp) >= extract ('hour' from '2011-07-13 20:00:00'::timestamp) or
    extract ('hour' from cal.stamp) <= extract ('hour' from '2011-07-31 15:11:21'::timestamp) 
  )
ORDER BY stamp ASC;

ここに魔法があるとすれば、それはおそらくこの節にあります。「または」の使用に注意してください。

AND (
  extract ('hour' from cal.stamp) >= extract ('hour' from '2011-07-13 20:00:00'::timestamp) or
  extract ('hour' from cal.stamp) <= extract ('hour' from '2011-07-31 15:11:21'::timestamp) 
)
于 2012-09-12T02:10:49.767 に答える