sql >> Databáze >  >> RDS >> Mysql

Detekce po sobě jdoucích položek splňujících určitá kritéria v časové řadě

Můj přístup k tomu:začněte s časovou řadou pozorování a každému dejte pořadové číslo.

Toto sériové číslování je v MySQL bolestí v krku, ale to nevadí. Máme-li tabulku se sloupcem ts (položka datetime) a sloupcem temp, zde je dotaz, jak je získat se sériovými čísly.

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

Podívejte se na tento sqlfiddle:http://sqlfiddle.com/#!2/ d81e2/5/0

Dobře, to je docela triviální. Nyní řekněme, že hledáme časová období, kdy je teplota 25 stupňů nebo vyšší. Abychom to mohli udělat, musíme časovou řadu rozsekat tak, aby vynechala ty postřehy. Zní to takto:

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

Zde je sqlfiddle:http://sqlfiddle.com/#!2/d81e2/6 /0

Nyní dalším trikem je najít časové mezery v této sekvenci. K tomu můžeme použít techniku ​​z tohoto příspěvku SO. Metoda hledání mezer v datech časových řad v MySQL?

V dalším kroku jej připojíme k sobě.

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)

Tento dotaz získá časovou mezeru mezi každou položkou v řadě a tou následující. Je to koncepčně jednoduchá věc, ale ve verzi SQL MySQL je to složité. Zde je celý dotaz.

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)

Zde je sqlfiddle:http://sqlfiddle.com/#!2/d81e2/13 /0 Všimněte si, že některé mezery trvají 30 minut. To je normální pro po sobě jdoucí čtení. Některé mají 60 minut. To je také normální, protože v časové řadě, kterou používám, chybí některé položky. Záznamy v této sadě výsledků ukazují časy a teploty bezprostředně před mezerami.

Nezbývá tedy, než se zbavit nevyžádaných mezer (30 a 60 minut) a poté seřadit zbývající mezery sestupně.

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

To dává jeden řádek pro každou časovou sekvenci, kde je teplota nad 25 stupňů; nejdříve nejdelší dobu. Položka zobrazená ve výsledkové sadě je poslední čas, kdy byla teplota nižší než 25, než vzrostla. SQL housle. http://sqlfiddle.com/#!2/d81e2/14/0

Zábava, co?




  1. Sledování času dotazování DB - Knihovna/knex

  2. Hibernate - ManyToOne &Inheritance / PŘIPOJEN / mappedBy

  3. SQLite JSON_PATCH()

  4. IllegalStateException:databáze již uzavřena (pomocí ViewPager)