Reputation: 1105
I have a MySQL table with data from car GPS tracker (lat, lng, speed, time). I want to select positions (latitude, longitude and time) where car has been stopped (speed = 0) longer than 10 min, 30 min, 1 hour etc.
My table looks like this:
id latitude longitude speed time ----------------------------------------------------------------------- 304 52.388983333333336 17.025338333333334 33.67 2014-03-26 08:00:04 305 52.39029 17.023776666666667 34.65 2014-03-26 08:00:14 306 52.391035 17.021631666666668 32.91 2014-03-26 08:00:24 307 52.39103166666666 17.01917 30.03 2014-03-26 08:00:34 308 52.39089833333333 17.01698 29.33 2014-03-26 08:00:44 309 52.390593333333335 17.01532 9.54 2014-03-26 08:00:54 310 52.39071333333333 17.015056666666666 0 2014-03-26 08:01:04 311 52.39105333333333 17.01499 10.3 2014-03-26 08:01:14 312 52.391485 17.01488 7.82 2014-03-26 08:01:24 313 52.391705 17.014815 0 2014-03-26 08:01:34 314 52.391705 17.014815 0 2014-03-26 08:01:44 315 52.391705 17.014815 0 2014-03-26 08:01:54 316 52.391705 17.014815 0 2014-03-26 08:02:04 317 52.391705 17.014815 0 2014-03-26 08:02:14 318 52.391705 17.014815 0 2014-03-26 08:02:24 319 52.39232333333333 17.014648333333334 7.12 2014-03-26 08:02:34 320 52.392345 17.014635 0 2014-03-26 08:02:44 321 52.392345 17.014635 0 2014-03-26 08:02:54 322 52.392345 17.014635 0 2014-03-26 08:03:04 323 52.392345 17.014635 0 2014-03-26 08:03:15 324 52.392345 17.014635 0 2014-03-26 08:03:25 325 52.392345 17.014635 0 2014-03-26 08:03:35 326 52.392558333333334 17.014471666666665 14.11 2014-03-26 08:03:45 327 52.392316666666666 17.012883333333335 27.47 2014-03-26 08:03:55 328 52.39194333333333 17.010871666666667 28.93 2014-03-26 08:04:05 329 52.39152333333333 17.00893 22.28 2014-03-26 08:04:15 330 52.391575 17.007181666666668 27.01 2014-03-26 08:04:25 331 52.39164 17.00501 26.48 2014-03-26 08:04:35 332 52.39159333333333 17.002895 28.34 2014-03-26 08:04:45 333 52.391641666666665 17.000795 26.39 2014-03-26 08:04:55 334 52.392156666666665 16.999178333333333 16.56 2014-03-26 08:05:05 335 52.39223666666667 16.998796666666667 0 2014-03-26 08:05:15 336 52.39234 16.99819 15.38 2014-03-26 08:05:25 337 52.39261166666667 16.996865 17.1 2014-03-26 08:05:35 338 52.392896666666665 16.995643333333334 20.91 2014-03-26 08:05:45 339 52.39313666666666 16.99468 7.5 2014-03-26 08:05:55 340 52.39331833333333 16.993918333333333 9.1 2014-03-26 08:06:05 341 52.3936 16.992806666666667 16.86 2014-03-26 08:06:15 342 52.393746666666665 16.992065 4.72 2014-03-26 08:06:25
I have a MySQL query that should do this, but it kills my database.
select speed, latitude, longitude, min(time) as StartTime, max(time) as EndTime from (select t.*, (select count(*) from positions t2 where t2.time 0 ) as grp from positions t ) t where time >= '$from' AND time = min(time) + interval 1 minute
I'm looking for other ideas how to find this positions with speed 0 and idle time.
For example:
Speed: 0
StartTime: 2014-03-26 08:01:34
EndTime: 2014-03-26 08:02:24
Looking for help, any ideas?
Upvotes: 1
Views: 530
Reputation: 32402
This selects positions that have been idle more than 10 minutes. The inner query selects all positions and idle times and the outer query filters by the minimum idle time. For the inner query an idle car will have a speed of 0 and at least 2 rows at the same position. The idle time is calculated by taking the difference between the maximum and minimum times at the same position.
SELECT * FROM
(SELECT
latitude,
longitude,
TIME_TO_SEC(TIMEDIFF(MAX(time),MIN(time))) idle_time
FROM positions
WHERE speed = 0
GROUP BY latitude, longitude
HAVING COUNT(*) > 1) t
WHERE idle_time > 600
As pointed out in the comments, the query above assumes that a vehicle will never return to the same position. If it's possible for a vehicle to return to the same position, we need to make sure that the grouped positions are consecutive. This is done in the query below by verifying that the car has not been at another position between the max and min times used for each grouping.
Not tested
SELECT * FROM
(SELECT
latitude,
longitude,
TIME_TO_SEC(TIMEDIFF(max_time,min_time)) idle_time
FROM (SELECT
latitude,
longitude,
(SELECT MIN(time)
FROM positions p2
WHERE p2.latitude = p1.latitude
AND p1.longitude = p2.longitude
AND NOT EXISTS (SELECT 1 FROM positions p3
WHERE p3.time < p1.time AND p3.time > p2.time
AND (p3.longitude != p2.longitude OR p3.latitude != p2.latitude))
) min_time,
(SELECT MAX(time)
FROM positions p2
WHERE p2.latitude = p1.latitude
AND p2.longitude = p1.longitude
AND NOT EXISTS (SELECT 1 FROM positions p3
WHERE p3.time > p1.time AND p3.time < p2.time
AND (p3.longitude != p2.longitude OR p3.latitude != p2.latitude))
) max_time
FROM positions p1
WHERE speed = 0)
GROUP BY latitude, longitude, min_time, max_time
HAVING COUNT(*) > 1) t
WHERE idle_time > 600
Upvotes: 3