7

1970 年 1 月 1 日からのミリ秒数としてイベントの作成時間を列に格納する 2 つの列(一意の主キー) とを含むeventsテーブルがあります。eventkeycreatetimeNUMBER

先週の各時間に作成されたイベントの数を示す「ヒストグラム」または度数分布を作成したいと考えています。

width_bucket()これは、関数を使用して Oracle でそのようなクエリを作成する最良の方法ですか? width_bucket各行が属するバケット番号を特定してそれ以上を行うのではなく、他の Oracle 分析関数のいずれかを使用して、各バケットに分類される行数を導き出すことは可能count(*)ですか?

-- 1305504000000 = 5/16/2011 12:00am GMT
-- 1306108800000 = 5/23/2011 12:00am GMT
select 
timestamp '1970-01-01 00:00:00' + numtodsinterval((1305504000000/1000 + (bucket * 60 * 60)), 'second') period_start,
numevents
from (
  select bucket, count(*) as events from (
    select eventkey, createtime, 
    width_bucket(createtime, 1305504000000, 1306108800000, 24 * 7) bucket
    from events 
    where createtime between 1305504000000 and 1306108800000
  ) group by bucket
) 
order by period_start
4

4 に答える 4

11

日付列の場合createtime、これは簡単です。

SELECT TO_CHAR(CREATE_TIME, 'DAY:HH24'), COUNT(*) 
  FROM EVENTS
 GROUP BY TO_CHAR(CREATE_TIME, 'DAY:HH24');

そのままでは、createtime列のキャストはそれほど難しくありません。

select TO_CHAR( 
         TO_DATE('19700101', 'YYYYMMDD') + createtime / 86400000), 
         'DAY:HH24') AS BUCKET, COUNT(*)
   FROM EVENTS
  WHERE createtime between 1305504000000 and 1306108800000
 group by TO_CHAR( 
         TO_DATE('19700101', 'YYYYMMDD') + createtime / 86400000), 
         'DAY:HH24') 
 order by 1

あるいは、フェンスポストの値を探している場合 (たとえば、最初の 10 分の 1 (0-10%) から次の 11-20% までのどこに行くか)、次のようにします。

select min(createtime) over (partition by decile) as decile_start,
       max(createtime) over (partition by decile) as decile_end,
       decile
  from (select createtime, 
               ntile (10) over (order by createtime asc) as decile
          from events
         where createtime between 1305504000000 and 1306108800000
       )
于 2011-06-01T13:47:22.577 に答える
3

私は Oracle の日付関数に慣れていませんが、この Postgres ステートメントを記述する同等の方法があることは確かです。

select date_trunc('hour', stamp), count(*)
from your_data
group by date_trunc('hour', stamp)
order by date_trunc('hour', stamp)
于 2011-06-01T13:47:57.720 に答える
1

Adamとほぼ同じ応答ですが、必要に応じてさらにフィルタリングしやすいように、period_startを時間フィールドとして保持することをお勧めします。

with
events as
(
    select rownum eventkey, round(dbms_random.value(1305504000000, 1306108800000)) createtime
    from dual
    connect by level <= 1000 
)
select
    trunc(timestamp '1970-01-01 00:00:00' + numtodsinterval(createtime/1000, 'second'), 'HH') period_start,
    count(*) numevents
from
    events
where
    createtime between 1305504000000 and 1306108800000
group by
    trunc(timestamp '1970-01-01 00:00:00' + numtodsinterval(createtime/1000, 'second'), 'HH')
order by
    period_start
于 2011-06-01T13:59:56.793 に答える