我有一堆每天每分钟都插入一行的记录。每行包含一个datetime时间戳(time)、一个值(0或1)和一个外键spotid。总共有100个点。
我需要看看从顶部开始,每个地点的“2017-01-01 00:00:00”和“2017-01-01 00:05:00”(5小时)两个时间戳之间的值1保持了多长时间。如果值为0,则计数器停止并移动到下一个spotid。
例如,这是我当前使用的查询,从理论上讲,最终查询应该如何通过它:
SELECT time, value, spotID FROM `records`
WHERE time BETWEEN '2017-01-01 00:00:00' AND '2017-01-01 05:00:00'
ORDER BY `spotID`, `time` DESC
+------------------------+----------------+-------------+
| time (datetime) | value (0 or 1) | spotID (fk) |
+------------------------+----------------+-------------+
| '2017-01-01 05:59:00' | 1 | 1 |
| '2017-01-01 05:58:00' | 1 | 1 |
| '2017-01-01 05:57:00' | 1 | 1 |
| ...consecutive 1's... |
| '2017-01-01 05:30:00' | 1 | 1 |
| '2017-01-01 05:29:00' | 0 | 1 |
| ...we hit 0, count 1's and move onto spotID 2... |
| '2017-01-01 05:59:00' | 1 | 2 |
| '2017-01-01 05:58:00' | 1 | 2 |
| '2017-01-01 05:57:00' | 1 | 2 |
| '2017-01-01 05:56:00' | 1 | 2 |
| ...consecutive 1's... |
| '2017-01-01 03:42:00' | 1 | 2 |
| '2017-01-01 03:41:00' | 0 | 2 |
| ...we hit 0, count 1's and move onto spotID 3... |
| '2017-01-01 05:59:00' | 0 | 3 |
| ...we hit 0, count 1's and move onto spotID 4... |
+------------------------+----------------+-------------+
最后的查询应该显示(如果我的数学是正确的):
+--------+---------+
| spotID | minutes |
+--------+---------+
| 1 | 29 |
| 2 | 137 |
| 3 | 0 |
| .. | .. |
| 100 | .. |
+--------+---------+
我只是不知道如何通过上面的查询并计算连续1的总和,直到到达第一个0为止(忽略后面的任何1,只移动到下一个spotid)。
编辑:
这是我当前的查询:
SELECT a.spotID, SUM(a.value) as minutes
FROM (
SELECT sr.time, sr.value, sr.spotID FROM `records` as sr
WHERE sr.time BETWEEN '2017-01-01 00:00:00' AND '2017-01-01 05:00:00'
ORDER BY sr.spotID, sr.time DESC
) a
GROUP BY a.spotID
它非常接近,但是,我仍然不知道如何让它排除值为0之后的任何行。我想知道我是否需要把一个箱子放在一起?
2条答案
按热度按时间wrrgggsh1#
如果每分钟插入一行,为什么不计算每个spotid的行数呢。
这样地?不确定它是否会运行,因为我只是在使用SQLFiddle。
iq3niunx2#
我会分两步完成。
我是这样解决的:
创建数据:
创建临时表并基于spotid插入
计算时差:
输出