Моят подход към това:започнете с времевите серии от наблюдения и дайте на всяко едно сериен номер.
Това серийно номериране е болка във врата в MySQL, но няма значение. Като се има предвид таблица с колона ts (елемент за дата и час) и колона temp, ето заявката за получаването им със серийни номера.
SELECT @sample:[email protected]+1 AS ser, ts, temp
FROM (
SELECT ts,temp
FROM t
ORDER BY ts
) C,
(SELECT @sample:=0) s
Разгледайте този sqlfiddle:http://sqlfiddle.com/#!2/ d81e2/5/0
Добре, това е доста тривиално. Сега, да кажем, че търсим периоди от време, в които температурата е 25 градуса или повече. За да направим това, трябва да нарежем времевия ред, така че да пропусне тези наблюдения. Това става така:
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
Ето sqlfiddle:http://sqlfiddle.com/#!2/d81e2/6 /0
Сега следващият трик е да намерите времевите пропуски в тази последователност. Можем да използваме техниката от тази публикация SO, за да направим това. Метод за намиране на пропуски в данните от времеви серии в MySQL?
Следващата стъпка, ние го присъединяваме към себе си.
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)
Тази заявка получава времевата разлика между всеки елемент от поредицата и този след него. Концептуално е лесно да се направи, но е сложно в MySQL версията на SQL. Ето пълната заявка.
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)
Ето sqlfiddle:http://sqlfiddle.com/#!2/d81e2/13 /0 Обърнете внимание, че някои от пропуските са с продължителност 30 минути. Това е нормално за последователни четения. Някои са 60 минути. Това също е нормално, защото времевият ред, който използвам, има някои липсващи записи. Записите в този набор от резултати показват времената и температурите непосредствено преди пропуските.
И така, всичко, което остава, е да се отървете от празнините за боклуци (30 и 60 минути) и след това да подредите останалите празнини в низходящ ред.
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
Това дава един ред за всяка последователност от време, където температурата е над 25 градуса; най-дългото време първо. Елементът, показан в набора с резултати, е последният път, когато температурата е под 25, преди да се повиши. SQL Fiddle. http://sqlfiddle.com/#!2/d81e2/14/0
Забавно, а?