简体   繁体   中英

Query to find idle time i.e GPS lat long showing same coordinates within 15 minutes

My GPS table in postgres has the schema with four fields as userid (int), latitude (float8), longitude (float8), recordedtime (time stamp). For every user, we get 2 records for every minute.

Need a query to find the users who spent more then 15 minutres in same GPS lat long value?

the sample records could be

Userid, Latitiude, Longitude, recordedtime 
============================================
'ID1',12.089475408,76.089890,2019-11-24 19:10:01
'ID1',12.089475408,76.089890,2019-11-24 19:10:31
'ID1',12.089475408,76.089890,2019-11-24 19:11:01
'ID1',12.089475408,76.089890,2019-11-24 19:10:31
'ID1',12.089475408,76.089890,2019-11-24 19:12:01
'ID1',12.089475408,76.089890,2019-11-24 19:10:31
....

..

Could anyone please provide the required query?

This CTE might be what you're looking for.

WITH j AS (
  SELECT userid,longitude,latitude,
    max(recordedtime)-min(recordedtime) AS timespent
  FROM t
  GROUP BY userid,longitude,latitude
) SELECT * FROM j
  WHERE timespent > interval '15 minute';

 userid | longitude | latitude  | timespent 
--------+-----------+-----------+-----------
 ID1    | 80.205480 | 13.082240 | 00:20:00
(1 Zeile)

Have you considered using PostGIS to deal with your points? Your use case seems pretty simple, but very quickly you might find yourself struggling to perform geospatial operations in your data model that are already solved in PostGIS.

In case you're interested, this is what you should do to create a geometry column based on your GPS coordinates:

ALTER TABLE t ADD COLUMN geom GEOMETRY;
UPDATE t SET geom = ST_SetSRID(ST_MakePoint(longitude, latitude),4326);

The value 4326 in the ST_SetSRID function stands for the Reference System WGS84. Check which one suits your coordinates.

And this is how the query would look like:

WITH j AS (
  SELECT userid,geom,
    max(recordedtime)-min(recordedtime) AS timespent
  FROM t
  GROUP BY userid,geom
) SELECT userid,ST_AsText(geom),timespent FROM j
  WHERE timespent > interval '15 minute';

 userid |        st_astext         | timespent 
--------+--------------------------+-----------
 ID1    | POINT(80.20548 13.08224) | 00:20:00
(1 Zeile)

Note : As mentioned by @JGH, this use case assumes that the coordinates are identical in order to compute the time spent in certain location. Your coordinates have six decimal places, which gives you a precision of 0.111 m . Long story short, if the coordinates deviate by a few meters it won't work. In PostGIS using ST_Buffer you can easily create a buffer of a given size and with ST_Within you can check if one of your points is inside of the buffer. The query below should give an idea on how to do this:

(Buffer of 50 meters)

WITH j AS (
  SELECT userid, recordedtime, geom,
    ST_Buffer(geom::GEOGRAPHY,50)::GEOMETRY AS buffer
  FROM t
) SELECT t.userid, max(t.recordedTime)-min(t.recordedTime) AS timespent 
  FROM t,j
  WHERE t.userid=j.userid AND ST_Within(t.geom,j.buffer) 
  GROUP BY t.userid
  HAVING max(t.recordedTime)-min(t.recordedTime) > INTERVAL '15 minute';

 userid | timespent 
--------+-----------
 ID1    | 00:22:00
(1 Zeile)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM