Mon approche à cela :commencez par la série chronologique d'observations et attribuez à chacune un numéro de série.
Cette numérotation de série est une douleur dans le cou de MySQL, mais peu importe. Étant donné une table avec une colonne ts (un élément datetime) et une colonne temp, voici la requête pour les obtenir avec des numéros de série.
SELECT @sample:[email protected]+1 AS ser, ts, temp
FROM (
SELECT ts,temp
FROM t
ORDER BY ts
) C,
(SELECT @sample:=0) s
Jetez un oeil à ce sqlfiddle :http://sqlfiddle.com/#!2/ d81e2/5/0
OK, c'est assez banal. Maintenant, disons que nous recherchons des périodes où la température est de 25 degrés ou plus. Pour ce faire, nous devons découper la série chronologique afin qu'elle omette ces observations. Cela se passe comme ceci :
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
Voici le sqlfiddle :http://sqlfiddle.com/#!2/d81e2/6 /0
Maintenant, la prochaine astuce consiste à trouver les intervalles de temps dans cette séquence. Nous pouvons utiliser la technique de ce poste SO pour le faire. Méthode de trouver des lacunes dans les données de séries chronologiques dans MySQL ?
Prochaine étape, nous le joignons à lui-même.
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)
Cette requête obtient l'intervalle de temps entre chaque élément de la série et celui qui le suit. Conceptuellement, c'est une chose simple à faire, mais délicate dans la version MySQL de SQL. Voici la requête complète.
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)
Voici le sqlfiddle :http://sqlfiddle.com/#!2/d81e2/13 /0 Notez que certains des trous durent 30 minutes. C'est normal pour des lectures consécutives. Certains durent 60 minutes. C'est également normal, car la série chronologique que j'utilise comporte des entrées manquantes. Les entrées de cet ensemble de résultats affichent les heures et les températures immédiatement avant les écarts.
Donc, il ne reste plus qu'à se débarrasser des vides inutiles (30 et 60 minutes) puis à ordonner les vides restants par ordre décroissant.
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
Cela donne une ligne pour chaque séquence de temps où la température est supérieure à 25 degrés ; le plus long d'abord. L'élément affiché dans le jeu de résultats est la dernière fois que la température a été inférieure à 25 avant qu'elle n'augmente. Violon SQL. http://sqlfiddle.com/#!2/d81e2/14/0
Amusant, hein ?