Il mio approccio a questo:iniziare con le serie temporali delle osservazioni e assegnare a ciascuna un numero di serie.
Questa numerazione di serie è un dolore al collo in MySQL, ma non importa. Data una tabella con una colonna ts (un elemento datetime) e una colonna temporanea, ecco la query per ottenerle con i numeri di serie.
SELECT @sample:[email protected]+1 AS ser, ts, temp
FROM (
SELECT ts,temp
FROM t
ORDER BY ts
) C,
(SELECT @sample:=0) s
Dai un'occhiata a questo sqlfiddle:http://sqlfiddle.com/#!2/ d81e2/5/0
OK, è abbastanza banale. Ora, diciamo che stiamo cercando periodi di tempo in cui la temperatura è di 25 gradi o superiore. Per fare ciò, dobbiamo tagliare la serie temporale in modo che ometta quelle osservazioni. Funziona così:
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
Ecco sqlfiddle:http://sqlfiddle.com/#!2/d81e2/6 /0
Ora il prossimo trucco è trovare gli intervalli di tempo in questa sequenza. Possiamo usare la tecnica di questo post SO per farlo. Metodo di trovare lacune nei dati delle serie temporali in MySQL?
Il prossimo passo, lo uniamo a se stesso.
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)
Questa query ottiene l'intervallo di tempo tra ciascun elemento della serie e quello successivo. È una cosa semplice da fare concettualmente, ma complicata nella versione MySQL di SQL. Ecco la domanda completa.
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)
Ecco sqlfiddle:http://sqlfiddle.com/#!2/d81e2/13 /0 Si noti che alcuni degli intervalli durano 30 minuti. È normale per letture consecutive. Alcuni sono 60 minuti. Anche questo è normale, perché la serie temporale che sto usando ha alcune voci mancanti. Le voci in questo set di risultati mostrano i tempi e le temperature immediatamente prima degli intervalli.
Quindi, non resta che sbarazzarsi dei gap spazzatura (30 e 60 minuti) e quindi ordinare i gap rimanenti in ordine decrescente.
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
Questo dà una riga per ogni sequenza di tempo in cui la temperatura è superiore a 25 gradi; prima il tempo più lungo. L'elemento mostrato nel set di risultati è l'ultima volta che la temperatura è stata inferiore a 25 prima che aumentasse. SQL Violino. http://sqlfiddle.com/#!2/d81e2/14/0
Divertente, eh?