2016-06-19 8 views
1

タイムスタンプの列がtmstmpのテーブルがありますが、この表には特定のイベントのログが含まれています。私は1分間隔以内に発生した最大数イベントを見つける必要があります。Oracleで最も密な1分を選択する方法

慎重にお読みください。

select count(*), TO_CHAR(tmstmp,'MI') 
    from log_table 
    group by TO_CHAR(tmstmp,'MI') 
    order by TO_CHAR(tmstmp,'MI'); 

それは第一の記録を取り、それが1分以内にすべてのレコードを選択するまで1日から先読みする必要があるとの合計数:私はませこのような画分との合計タイムスタンプが分を抽出したいですレコードは、その後、第二とり、など同じことを行う。..

をし、その結果としてのレコードセット(合計、開始タイムスタンプ)がなければなりません。

誰でもコードの一部がどこかにあり、気をつけてください。

+0

あなたはすでにこの問題を確認しました: -

は、最大の分はサブクエリを使用取得する(MAX数で、あなたはより多くのその1つのレコードを受け取ることを忘れないでください)? http://stackoverflow.com/questions/14989927/sql-sliding-window-finding-max-value-over-interval私はそれがあまりにも1分間隔で適合させることができると仮定します。ありがとう。 –

答えて

5

分析機能は、直接この情報を提供することができます

select l.tmstmp, 
count(*) over (order by tmstmp range between current row and interval '59.999999' second following) cnt 
from log_table l 
order by 1 
; 

TMSTMP        CNT 
--------------------------- ---------- 
01.01.16 00:00:00,000000000   4 
01.01.16 00:00:10,000000000   4 
01.01.16 00:00:15,000000000   3 
01.01.16 00:00:20,000000000   2 
01.01.16 00:01:00,000000000   3 
01.01.16 00:01:40,000000000   2 
01.01.16 00:01:50,000000000   1 

あなたの精度のインターバルの長さを調整してください。 1分未満で可能な限り高い値でなければなりません。

with tst as (
select l.tmstmp, 
count(*) over (order by tmstmp range between current row and interval '59.999999' second following) cnt 
from log_table l) 
select * from tst where cnt = (select max(cnt) from tst); 

TMSTMP        CNT 
--------------------------- ---------- 
01.01.16 00:00:00,000000000   4 
01.01.16 00:00:10,000000000   4 
+0

@CarloCeは面白いソリューションを提供していましたが、このソリューションは、われわれのプロデュースされたexadataで文字通り20倍高速に動作します。 –

2

一つの方法は、使用joinと集約:

select t.* 
from (select l.tmstmp, count(*) 
     from log_table l join 
      log_table l2 
      on l2.tmstmp >= l.tmstmp and 
       l2.tmstmp < l.tmstmp + interval '1' minute 
     group by l.tmpstmp 
     order by count(*) desc 
    ) t 
where rownum = 1; 

注:これはtmstmp、各行に一意であることを前提としています。これが当てはまらない場合、サブクエリは、が一意である列で集計する必要があります。です。

EDIT:大規模データ用

は、累積和を利用し、より効率的な方法があります:

select tmstamp - interval 1 minute as starttm, tmstamp as endtm, cumulative 
from (select tmstamp, sum(inc) over (order by tmstamp) as cumulative 
     from (select tmstamp, 1 as inc from log_table union all 
      select tmstamp + interval '1' day, -1 as inc from log_table 
      ) t 
     order by sum(inc) over (order by tmstamp) desc 
    ) t 
where rownum = 1; 
+0

ありがとう。非常に徹底的な答え..しかし、動作しません..あなたは間隔のパラーム '+間隔 '1''の周りに引用符がありません..拳のSQLは60kの記録上に永遠に行く..私はatmを探しています.. 2番目のリターン1レコードのみ –

2

私はあなたが以下のように、SELECT文でサブクエリを使用してあなたの目標を達成することができると思います:論理ウィンドウで

SELECT tmstmp, (
    SELECT COUNT(*) 
    FROM log_table t2 
    WHERE t2.tmstmp >= t.tmstmp AND t2.tmstmp < t.tmstmp + 1/(24*60) 
) AS events 
FROM log_table t; 
+0

非常にテストするのは難しいですが、それは動作します。それは速く働く! –

関連する問題