3

次のようなMySQLテーブルがあります。

CREATE TABLE IF NOT EXISTS `mytable` (
  `ts` datetime NOT NULL,
  `cnt` int(10) unsigned NOT NULL,
  PRIMARY KEY (`ts`)
) ENGINE=InnoDB;

更新を取得するたびに、イベント カウンターの値を格納します。これらの更新は任意の時間に到着します。

X 時間 (5 分、1 日、1 か月など) ごとにイベント数を抽出するにはどうすればよいですか? これを、日付/時刻の SQL 関数 (時間、日、月など) を介して簡単に抽出できる間隔に単純化できます。

保証はありませんが、抽出したい間隔と比較すると、平均データは「密」です。例えば。通常、データは 1 時間ごとに複数回送信されますが、1 時間未満の間隔でイベントの数を求めることは決してありません。格納されたデータに「問題」(大きな穴など) がある場合、結果に「問題」があることは許容されます。

例として、次のようなクエリを使用して、関心のあるカウンター値を取得できます (24 時間の例)。

SELECT ts, cnt
FROM mytable
GROUP BY DATE( ts ) 
ORDER BY ts DESC

...そして、イベント数は、各行のカウンターをその前のカウンターから差し引くことで簡単に計算できます。しかし、可能であれば、SQLでそれを行いたいです。

また、この問題に適切な名前があれば (時系列とカウンターを扱う場合はかなり一般的な名前だと思います)、ボキャブラリーを改善するためにそれを知りたいです :)

4

1 に答える 1

3

テーブルに AUTO_INCREMENT PRIMARY KEY を追加する場合、それは解決可能です。

あなたが提示したテーブルスキーマは無効です(PRIMARY KEY on timestamp、しかしそのような列はありません)。

よろしければ:

ALTER TABLE mytable DROP PRIMARY KEY, ADD COLUMN id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY

?

もしそうなら、次のことを行うことができます。手順を示します。

SELECT
  TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS diff_seconds,
  m2.cnt - m1.cnt AS diff_cnt
FROM
  mytable m1 JOIN mytable m2 ON (m1.id = m2.id-1)
;

上記は、連続するサンプル間の時間と cnt の差を示しています。3 番目の列を追加しましょう。

SELECT
  TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS diff_seconds,
  m2.cnt - m1.cnt AS diff_cnt,
  (m2.cnt - m1.cnt)/TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS cnt_per_second
FROM
  mytable m1 JOIN mytable m2 ON (m1.id = m2.id-1)
;

cnt_per_second を評価しました。1 分あたりの cnt を取得するには、60 を掛けます。

さて、合計平均は次のようになります。

SELECT 
  avg(cnt_per_second)
FROM (
  SELECT
    TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS diff_seconds,
    m2.cnt - m1.cnt AS diff_cnt,
    (m2.cnt - m1.cnt)/TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS cnt_per_second
  FROM
    mytable m1 JOIN mytable m2 ON (m1.id = m2.id-1)
) sel_diff
;

差分がいつ記録されたかを知りたい場合は、元の n1.ts を最初のクエリに追加します。これにより、特定の期間の平均イベント数も知ることができます。

于 2012-07-07T04:29:19.030 に答える