这是一种方法。
首先按时间戳顺序获取状态行(内联视图别名为
s)。然后,在处理每一行时,请使用MySQL用户变量保留前几行的值。
我们真正要寻找的是紧随一系列“下降”状态之后的“上升”状态。当我们发现该行的状态为“ up”时,我们真正需要的是前一系列“ down”状态中的最早时间戳。
因此,类似这样的方法将起作用:
SELECt d.start_down , d.ended_down FROM (SELECt @i := @i + 1 AS i , @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down , @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down , @status := s.status FROM (SELECt t.time , t.status FROM mydata t WHERe t.status IN ('up','down') ORDER BY t.time ASC, t.status ASC ) s JOIN (SELECt @i := 0, @status := 'up', @ended := NULL, @start := NULL) i ) dWHERe d.start_down IS NOT NULL AND d.ended_down IS NOT NULL这适用于您显示的特定数据集。
这不能处理的(不返回的内容)是尚未结束的“下降”时间段,即一系列“下降”状态,后面没有“上升”状态。
为避免文件排序操作按顺序返回行,您需要在上包含覆盖索引
(time,status)。该查询将生成一个临时(MyISAM)表,以实现别名为的内联视图
d。
注意: 要了解此查询的功能,请剥离该最外面的查询,然后仅对别名为的内联视图运行查询
d(可以将其添加
s.time到选择列表中。)
该查询使每一行都具有“ up”或“
down”状态。“技巧”是它仅在结束“下降”时间段的行上分配“开始”和“结束”时间(标记下降时间)。(也就是说,第一行的状态为“ up”,紧随其后的状态为“
down”。)这是完成实际工作的地方,最外面的查询只是过滤掉该结果集中的所有“多余”行(不需要。)
SELECT @i := @i + 1 AS i , @start := IF(s.status = 'down' AND (@status = 'up' OR @i = 1), s.time, @start) AS start_down , @ended := IF(s.status = 'up' AND @status = 'down', s.time, NULL) AS ended_down , @status := s.status , s.time FROM (SELECt t.time , t.status FROM mydata t WHERe t.status IN ('up','down') ORDER BY t.time ASC, t.status ASC ) s JOIN (SELECT @i := 0, @status := 'up', @ended := NULL, @start := NULL) i内联视图别名的目的
s是按时间戳值对行进行排序,因此我们可以按顺序处理它们。内联视图的别名
i就在那里,因此我们可以在查询开始时初始化一些用户变量。
如果我们在Oracle或SQL Server上运行,则可以使用“解析函数”或“排名函数”(分别命名)。MySQL不提供类似的功能,因此我们必须“自行滚动”
”。



