sql >> Database >  >> RDS >> Mysql

Detecteer opeenvolgende items die voldoen aan bepaalde criteria in een tijdreeks

Mijn benadering hiervan:begin met de tijdreeksen van waarnemingen, en geef ze allemaal een volgnummer.

Deze serienummering is een pijn in de nek in MySQL, maar het maakt niet uit. Gegeven een tabel met een ts-kolom (een datetime-item) en een tijdelijke kolom, hier is de vraag om ze met serienummers te krijgen.

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

Kijk eens naar deze sqlfiddle:http://sqlfiddle.com/#!2/ d81e2/5/0

Oké, dat is vrij triviaal. Laten we zeggen dat we zoeken naar perioden waarin de temperatuur 25 graden of hoger is. Om dit te doen, moeten we de tijdreeks opdelen zodat deze weglaat die waarnemingen. Dat gaat als volgt:

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

Hier is de sqlfiddle:http://sqlfiddle.com/#!2/d81e2/6 /0

Nu is de volgende truc om de tijdhiaten in deze reeks te vinden. We kunnen de techniek uit deze SO-post gebruiken om dat te doen. Methode van het vinden van hiaten in tijdreeksgegevens in MySQL?

De volgende stap voegen we toe aan zichzelf.

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)

Met deze zoekopdracht wordt het tijdsverschil tussen elk item in de reeks en het volgende item opgehaald. Het is een eenvoudig ding om conceptueel te doen, maar lastig in de MySQL-versie van SQL. Hier is de volledige vraag.

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)

Hier is de sqlfiddle:http://sqlfiddle.com/#!2/d81e2/13 /0 Merk op dat sommige onderbrekingen 30 minuten duren. Dat is normaal voor opeenvolgende metingen. Sommige zijn 60 minuten. Dat is ook normaal, want de tijdreeks die ik gebruik heeft enkele ontbrekende vermeldingen. De gegevens in deze resultatenset tonen de tijden en temperaturen direct voor de gaten.

Het enige dat overblijft is om de rommelgaten (30 en 60 minuten) weg te werken en vervolgens de resterende gaten in aflopende volgorde te ordenen.

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

Dit geeft één rij voor elke tijdreeks waarin de temperatuur boven de 25 graden is; de langste tijd eerst. Het item dat in de resultatenset wordt weergegeven, is de laatste tijd dat de temperatuur onder de 25 was voordat deze steeg. SQL viool. http://sqlfiddle.com/#!2/d81e2/14/0

Leuk, hè?




  1. MySQL-tabelnamen in kleine letters in Windows-namen in hoofdletters op Unix

  2. Verbind Entity Framework met MYSQL in VS2019

  3. Trage zoekopdracht bij gebruik van ORDER BY

  4. Voorkom dat formulier opnieuw wordt ingediend nadat op de knop Terug is geklikt