sql >> データベース >  >> RDS >> Mysql

時系列で特定の基準を満たす連続したアイテムを検出する

    これに対する私のアプローチ:観測の時系列から始めて、それぞれにシリアル番号を付けます。

    このシリアル番号はMySQLの首の痛みですが、関係ありません。 ts列(日時アイテム)と一時列を持つテーブルがある場合、シリアル番号でそれらを取得するためのクエリは次のとおりです。

    SELECT @sample:[email protected]+1 AS ser, ts, temp
      FROM (
         SELECT ts,temp
           FROM t
          ORDER BY ts
        ) C,
      (SELECT @sample:=0) s 
    

    このsqlfiddleを見てください: http://sqlfiddle.com/#!2/ d81e2 / 5/0

    OK、それはかなり些細なことです。ここで、気温が25度以上の期間を探しているとしましょう。これを行うには、時系列を切り刻んで省略する必要があります。 それらの観察。これは次のようになります:

    SELECT @sample:[email protected]+1 AS ser, ts, temp
      FROM (
         SELECT ts,temp
           FROM t
          WHERE NOT temp >= 25
          ORDER BY ts
        ) C,
      (SELECT @sample:=0) s
    

    sqlfiddleは次のとおりです。 http://sqlfiddle.com/#!2/d81e2/6 / 0

    次のトリックは、このシーケンスの時間ギャップを見つけることです。このSO投稿の手法を使用してそれを行うことができます。 メソッドMySQLで時系列データのギャップを見つける方法は?

    次のステップでは、それを結合します。

    SELECT two.ser, two.ts, two.temp, 
           TIMESTAMPDIFF(MINUTE, two.ts, one.ts) gap
      FROM (
         /* virtual table */
      ) ONE
      JOIN (
         /* same virtual table */
      ) TWO ON (TWO.ser+ 1 = ONE.ser)
    

    このクエリは、シリーズの各アイテムとその次のアイテムの間の時間差を取得します。概念的に行うのは簡単ですが、MySQLバージョンのSQLでは注意が必要です。これが完全なクエリです。

    SELECT two.ser, two.ts, two.temp, 
           TIMESTAMPDIFF(MINUTE, two.ts, one.ts) gap
          FROM (
     SELECT @sample:[email protected]+1 AS ser, ts, temp
      FROM (
         SELECT ts,temp
           FROM t
          WHERE NOT temp >= 25
          ORDER BY ts
        ) C,
      (SELECT @sample:=0) s
          ) ONE
          JOIN (
    SELECT @sample2:[email protected]+1 AS ser, ts, temp
      FROM (
         SELECT ts,temp
           FROM t
          WHERE NOT temp >= 25
          ORDER BY ts
        ) C,
      (SELECT @sample2:=0) s
          ) TWO ON (TWO.ser+ 1 = ONE.ser)
    

    sqlfiddleは次のとおりです。 http://sqlfiddle.com/#!2/d81e2/13 / 0 一部のギャップの長さは30分であることに注意してください。これは、連続した読み取りでは正常です。 60分もあります。私が使用している時系列にはいくつかのエントリが欠落しているため、これも正常です。この結果セットのエントリは、ギャップの直前の時間と温度を示しています。

    したがって、残っているのは、ジャンクギャップ(30分と60分)を取り除き、残りのギャップを降順で並べ替えることだけです。

    SELECT two.ts, two.temp, 
           TIMESTAMPDIFF(MINUTE, two.ts, one.ts) gap
          FROM (
     SELECT @sample:[email protected]+1 AS ser, ts, temp
      FROM (
         SELECT ts,temp
           FROM t
          WHERE NOT temp >= 25
          ORDER BY ts
        ) C,
      (SELECT @sample:=0) s
          ) ONE
          JOIN (
    SELECT @sample2:[email protected]+1 AS ser, ts, temp
      FROM (
         SELECT ts,temp
           FROM t
          WHERE NOT temp >= 25
          ORDER BY ts
        ) C,
      (SELECT @sample2:=0) s
          ) TWO ON (TWO.ser+ 1 = ONE.ser)
     WHERE TIMESTAMPDIFF(MINUTE, two.ts, one.ts)> 60
     ORDER BY TIMESTAMPDIFF(MINUTE, two.ts, one.ts) DESC
    

    これにより、温度が25度を超える時間のシーケンスごとに1つの行が得られます。最初に最長の時間。結果セットに表示されている項目は、最後に気温が25度を下回ってから上昇したときのものです。 SQLフィドル。 http://sqlfiddle.com/#!2/d81e2/14/0

    楽しいね?




    1. 挿入および更新されたMYSQLレコード数

    2. MicrosoftAccessエラーチェックマーカーを停止または制御する方法

    3. 再帰機能を備えたエコーメニューツリー

    4. 一意のインデックスを持つSQLクローンレコード