I believe this is correct (see the SQL Fiddle to test it):
SELECT
s1.id AS stopped_row_id, MIN(s2.id) AS departed_row_id, TIMESTAMPDIFF(SECOND, s1.timestamp, MIN(s2.timestamp)) AS stopped_seconds
FROM
stops AS s1
JOIN stops AS s2 ON
s1.imei = s2.imei
AND s1.id < s2.id
AND (s1.timestamp + INTERVAL 4 MINUTE) <= s2.timestamp
JOIN stops AS s3 ON
s1.imei = s2.imei
AND s3.id = s1.id - 1
LEFT JOIN stops AS s4 ON
s1.imei = s2.imei
AND s4.id BETWEEN (s1.id + 1) AND (s2.id - 1)
AND s4.speed <> 0
WHERE
s1.speed = 0
AND s2.speed <> 0
AND s3.speed <> 0
AND s4.id IS NULL
AND s1.imei = 7466 -- optional; query will also give results for all imei if wanted
AND s1.timestamp BETWEEN '2013-08-20 00:00:00' AND '2013-08-20 23:59:59' -- optional, query will give results for entire table if wanted
GROUP BY
s1.id,
s1.timestamp
In this query, s1
is the 'main' table.
s2
is joined to provide all rows with higher id
s than that of s1
where the timestamp
is at least 4 minutes higher than that of s1
(so in essence s2
is all rows indicating pauses long enough that the row from s1
should go into the final result set).
s3
is joined to make sure that the row in s1
is the first row where speed
is 0 (for your example where there are sets of rows where speed
is 0).
s4
is joined to make sure that there are no non-zero-speed rows between the 'selected' rows from s1
and s2
.
The GROUP BY
makes sure that we can get the first timestamp in the future where speed
is not 0 by using MIN()
.
Apparently, the rows are not in a strict descending or ascending order (even if the IDs are). I have reworked the query to only use the time as 'sorting mechanism'. Note that this makes the query very slow, and you might be better off by ordering the table or a solution in the style of that of @peterm. Or at least adding an index on id
andtimestamp
.
SELECT
s1.timestamp AS stopped_timestamp, MAX(s2.timestamp) as departed_timestamp, TIMESTAMPDIFF(SECOND, s1.timestamp, MAX(s2.timestamp)) AS stopped_seconds
FROM
stops AS s1
JOIN stops AS s2 ON
s1.imei = s2.imei
AND (s1.timestamp + INTERVAL 4 MINUTE) <= s2.timestamp
JOIN stops AS s3 ON
s1.imei = s2.imei
LEFT JOIN stops AS s4 ON
s1.imei = s2.imei
AND s4.timestamp BETWEEN (s1.timestamp + INTERVAL 1 SECOND) AND (s2.timestamp - INTERVAL 1 SECOND)
AND s4.speed <> 0
WHERE
s1.speed = 0
AND s2.speed <> 0
AND s3.speed <> 0
AND s4.id IS NULL
AND s1.imei = 7466 -- optional; query will also give results for all imei if wanted
AND s1.timestamp BETWEEN '2013-08-20 00:00:00' AND '2013-08-20 23:59:59' -- optional, query will give results for entire table if wanted
AND s3.timestamp = (SELECT MAX(s5.timestamp) FROM stops AS s5 WHERE s5.timestamp < s1.timestamp)
GROUP BY
s1.id,
s1.timestamp