sql >> Database teknologi >  >> RDS >> Mysql

Opdag på hinanden følgende elementer, der opfylder bestemte kriterier i en tidsserie

Min tilgang til dette:start med tidsrækken af ​​observationer, og giv hver enkelt et serienummer.

Denne serienummerering er en smerte i nakken i MySQL, men lige meget. Givet en tabel med en ts-kolonne (et datetime-element) og en temp-kolonne, er her forespørgslen for at få dem med serienumre.

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

Tag et kig på denne sqlfiddle:http://sqlfiddle.com/#!2/ d81e2/5/0

OK, det er ret trivielt. Lad os nu sige, at vi leder efter perioder, hvor temperaturen er 25 grader eller derover. For at gøre dette skal vi skære tidsserien op, så den udelades disse observationer. Det går sådan her:

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

Her er sqlfiddle:http://sqlfiddle.com/#!2/d81e2/6 /0

Nu er det næste trick at finde tidshullerne i denne sekvens. Det kan vi bruge teknikken fra dette SO-indlæg til. Metode at finde huller i tidsseriedata i MySQL?

Næste trin forbinder vi det med sig selv.

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)

Denne forespørgsel henter tidsforskellen mellem hvert element i serien og det efter det. Det er en ligetil ting at gøre konceptuelt, men vanskelig i MySQL-versionen af ​​SQL. Her er hele forespørgslen.

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)

Her er sqlfiddle:http://sqlfiddle.com/#!2/d81e2/13 /0 Bemærk, at nogle af hullerne er på 30 minutter. Det er normalt for på hinanden følgende aflæsninger. Nogle er 60 minutter. Det er også normalt, fordi den tidsserie, jeg bruger, mangler nogle poster. Indtastningerne i dette resultatsæt viser tiderne og temperaturerne umiddelbart før hullerne.

Så det eneste, der er tilbage, er at slippe af med uønsket huller (30 og 60 minutter) og derefter bestille de resterende huller i faldende rækkefølge.

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

Dette giver en række for hver tidssekvens, hvor temperaturen er over 25 grader; den længste tid først. Punktet vist i resultatsættet er den sidste tidstemperatur under 25, før den steg. SQL violin. http://sqlfiddle.com/#!2/d81e2/14/0

Sjovt, ikke?




  1. PostgreSQL-fejl:Fatal:rollebrugernavn findes ikke

  2. Hvordan kan jeg slutte mig til flere borde i symfony2?

  3. MySQL 5.7 RAND() og IF() uden LIMIT fører til uventede resultater

  4. Java, hvordan ændres nuværende database til en anden?