【问题标题】:Detect consecutive items meeting particular criteria in a time series在时间序列中检测满足特定标准的连续项目
【发布时间】:2013-06-11 03:46:08
【问题描述】:

我有一个 MySQL 数据库,其中包含超过 92.000 行的天气记录,每半小时一次。 天 |月 |年份 |时间 |温度 |... 我正在尝试获取(在 PHP 中)峰值温度:显示每个月温度 =

我将不胜感激!

【问题讨论】:

  • 将一些示例数据放在 sqlfiddle.com 上并展示一些关于您尝试过的内容可能对您有意义。
  • 我不知道的是如何计算连续的寄存器...我的意思是,连续多少次满足条件。
  • 这是一个可能的起点。 stackoverflow.com/questions/11085596/…

标签: php mysql time-series


【解决方案1】:

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

这个序列号在 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 中的技术来做到这一点。 Method of finding gaps in time series data in 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

有趣,嗯?

【讨论】:

  • 非常感谢您的回答,我会尽快尝试。
  • 以适当的方式消化这段代码对我来说很复杂,但我可以根据我的数据调整它,经过 16 分钟的处理我可以获得结果。是否可以按月分组?
  • 您可以在两个子查询中选择一个时间子集。但是请注意,当您逐月进行时,您的测量结果可能会有点失真。从 6 月的最后几天开始并一直持续到 7 月的热浪不会出现。
  • 这个查询在我的笔记本电脑上用了两分钟,数据集大约有 73K 的观察结果。
猜你喜欢
  • 1970-01-01
  • 2013-02-05
  • 1970-01-01
  • 2016-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 1970-01-01
相关资源
最近更新 更多