我有一个 MySQL 数据库,每半小时就有超过 92.000 行天气记录。天 | 月 | 年份 | 时间 | 温度 |... 我正在尝试获取(在 PHP 中)峰值温度:显示每个月温度 =< 分钟(温度)+3 的最大时间量(连续寄存器)。
我将不胜感激任何帮助!
我有一个 MySQL 数据库,每半小时就有超过 92.000 行天气记录。天 | 月 | 年份 | 时间 | 温度 |... 我正在尝试获取(在 PHP 中)峰值温度:显示每个月温度 =< 分钟(温度)+3 的最大时间量(连续寄存器)。
我将不胜感激任何帮助!
我的方法是:从观察的时间序列开始,给每个观察一个序列号。
这个序列号在 MySQL 中是一件令人头疼的事情,但没关系。给定一个包含 ts 列(日期时间项)和 temp 列的表,下面是用序列号获取它们的查询。
SELECT @sample:=@sample+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:=@sample+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 post 中的技术来做到这一点。在 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:=@sample+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:=@sample2+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:=@sample+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:=@sample2+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小提琴。 http://sqlfiddle.com/#!2/d81e2/14/0
好玩,嗯?