1

これは、mysqlクエリの日付と期間の計算に似ていますが、使用する一意のID列がなく、開始点/終了点ではないサンプルがある点が異なります。

興味深い実験として、cronをに設定しましたps aux > 'date +%Y-%m-%d_%H-%M'.txt。現在、「マシンが実行していたもの」のサンプルが約250,000あります。

これを「プロセス|コマンド|開始|停止」のリストに変換したいと思います。'start'イベントはペアが存在する最初の時間であり、'stop'イベントはそれが存在しなくなった最初のサンプルであると想定されます。サンプルが「欠落」する可能性はありません。

とは言うものの、この変換を行うには、できればSQLを使用する方法があります(SQLが好きであるという理由で、これは素晴らしい挑戦のようです)。pidを繰り返すことができないと仮定すると、これは簡単な作業です(すべてをテーブルに入れますSELECT MIN(time), MAX(time), pid GROUP BY pid)。ただし、PID / cmdのペアが繰り返されるため(チェックしたところ、重複があります)、真の「隣接するすべてのセグメントを検索」検索を実行するメソッドが必要です。

必要に応じて、私は何らかの形で何かをすることができます

Load file0 -> oldList
ForEach fileN:
    Load fileN ->newList
    oldList-newList = closedN
    newList-oldList = openedN
    oldList=newList

しかし、それはSQLではなく、興味深いものでもありません。そして、誰が知っているか、私はある時点でこのプロパティを処理するための実際のSQLデータを持ってしまうかもしれません。

最初にdiffのテーブルを作成し、次にすべてのクローズをすべてのオープンに対して結合し、オープンするたびに最小距離を閉じるというものを考えていますが、もっと良い方法があるかどうか疑問に思っています。

4

1 に答える 1

1

使用しているデータベースについては言及していません。ソリューションが単純化されるため、ランキング関数をサポートするデータベースを使用していると仮定します。

これを解決するための鍵は観察です。各pidにIDを割り当てて、それが一意であるかどうかを確認します。以前のタイムスタンプ付きの出力にpidが表示されなかった場合、pidは単一のプロセスを表すと想定します。

さて、アイデアは次のとおりです。

  1. 出力の各セットに連番を割り当てます。psへの最初の呼び出しは、日付に基づいて1、次の2などを取得します。
  2. 日付に基づいて、各pidに連番を割り当てます。最初の出現は1、次の出現は2、というようになります。
  3. 順番に表示されるpidの場合、差は一定です。これをそのセットのグループIDと呼ぶことができます。

したがって、これは実際のクエリです。

select groupid, pid, min(time), max(time)
from (select t.*,
             (dense_rank() over (order by time) -
              row_number() over (partition by pid order by time)
             ) as groupid
      from t
     ) t
group by groupid, pid

これは、ほとんどのデータベース(SQL Server、Oracle、DB2、Postgres、Teradataなど)で機能します。MySQLはウィンドウ/分析機能をサポートしていないため、MySQLでは機能しません。

于 2012-09-14T20:34:17.320 に答える