1

我有一个 MySQL 数据库,每半小时就有超过 92.000 行天气记录。天 | 月 | 年份 | 时间 | 温度 |... 我正在尝试获取(在 PHP 中)峰值温度:显示每个月温度 =< 分钟(温度)+3 的最大时间量(连续寄存器)。

我将不胜感激任何帮助!

4

1 回答 1

0

我的方法是:从观察的时间序列开始,给每个观察一个序列号。

这个序列号在 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

好玩,嗯?

于 2013-06-17T02:31:26.137 回答