Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从GPS日志计算用户的距离和持续时间_Sql_Postgresql_Gps_Aggregate Functions_Postgis - Fatal编程技术网

Sql 从GPS日志计算用户的距离和持续时间

Sql 从GPS日志计算用户的距离和持续时间,sql,postgresql,gps,aggregate-functions,postgis,Sql,Postgresql,Gps,Aggregate Functions,Postgis,我正在使用一个全球定位系统数据集的人的流动性为。在我的原始GPS表中,轨迹是所有用户的GPS序列: CREATE TABLE trajectories ( user_id integer, session_id bigint NOT NULL, "timestamp" timestamp with time zone NOT NULL, lat double precision NOT NULL, lon double precision NOT NULL

我正在使用一个全球定位系统数据集的人的流动性为。在我的原始GPS表中,轨迹是所有用户的GPS序列:

CREATE TABLE trajectories
(
    user_id integer,
    session_id bigint NOT NULL,
    "timestamp" timestamp with time zone NOT NULL,
    lat double precision NOT NULL,
    lon double precision NOT NULL,
    alt double precision,
    CONSTRAINT trajectories_pkey PRIMARY KEY (session_id, "timestamp")
);

SELECT * FROM trajectories ORDER BY user_id, timestamp LIMIT 10;
 user_id |   session_id   |       timestamp        |    lat    |    lon     | alt 
---------+----------------+------------------------+-----------+------------+-----
       1 | 20081023025304 | 2008-10-23 02:53:04+01 | 39.984702 | 116.318417 | 492
       1 | 20081023025304 | 2008-10-23 02:53:10+01 | 39.984683 |  116.31845 | 492
       1 | 20081023025304 | 2008-10-23 02:53:15+01 | 39.984686 | 116.318417 | 492
       1 | 20081023025304 | 2008-10-23 02:53:20+01 | 39.984688 | 116.318385 | 492
       1 | 20081023025304 | 2008-10-23 02:53:25+01 | 39.984655 | 116.318263 | 492
       1 | 20081023025304 | 2008-10-23 02:53:30+01 | 39.984611 | 116.318026 | 493
       1 | 20081023025304 | 2008-10-23 02:53:35+01 | 39.984608 | 116.317761 | 493
       1 | 20081023025304 | 2008-10-23 02:53:40+01 | 39.984563 | 116.317517 | 496
       1 | 20081023025304 | 2008-10-23 02:53:45+01 | 39.984539 | 116.317294 | 500
       1 | 20081023025304 | 2008-10-23 02:53:50+01 | 39.984606 | 116.317065 | 505
(10 rows)
上面的SELECT查询显示了用户1的GPS点序列,从当前行程会话的起始点_id=20081023025304开始。我想使用此表中的原始数据将计算出的出行指标插入一个新表中,我定义为:

CREATE TABLE trip_metrics(
  user_id INT,
  session_id BIGINT,
  lat_start DOUBLE PRECISION,
  lat_end DOUBLE PRECISION,
  lon_start DOUBLE PRECISION,
  lon_end DOUBLE PRECISION,
  trip_starttime timestamp,
  trip_endtime timestamp,
  trip_duration DOUBLE PRECISION,
  trip_distance DOUBLE PRECISION,
  PRIMARY KEY (user_id, session_id, trip_starttime)
  );
此trip_metrics表的要点是存储分析结果,以便lat_start,lon_start取给定示例中起始位置的lat,lon值:39.984702,116.318417,trip_starttimestamp在本例中取起始时间2008-10-23 02:53:04+01,因此lat_end,lon_end,trip_endtime分别取起始时间

最后使用lat_start/end、lon_start/end来计算该用户在这次旅行中所覆盖的距离。最终结果应该是:

+---------+----------------+-----------+-----------+------------+------------+------------------------+------------------------+---------------+---------------+
| user_id |   session_id   | lat_start |  lat_end  | lon_start  |  lon_end   |     trip_starttime     |      trip_endtime      | trip_duration | trip_distance |
+---------+----------------+-----------+-----------+------------+------------+------------------------+------------------------+---------------+---------------+
|       1 | 20081023025304 | 39.984702 | 39.984606 | 116.318417 | 116.317065 | 2008-10-23 02:53:04+01 | 2008-10-23 02:53:50+01 |               |               |
+---------+----------------+-----------+-----------+------------+------------+------------------------+------------------------+---------------+---------------+
计算行程持续时间和行程距离后,行程持续时间的值当然是行程结束时间-行程开始时间

几天来,我一直在研究如何在PostgrSQL数据库中实现这一点,只过滤北京市纬度39.85-40.05和经度116.25-116.5范围内的旅行,因为有些旅行跨越城市之外。我为这个用户创建了一个包含2次旅行的GPS点的db小提琴,每个10点

我将非常感谢任何关于这方面的指导,以便在我目前的研究中取得进展

编辑

遇到此函数时,可以使用haversine公式计算距离。我创建了这个函数,但我不知道如何使用它来获得trip_distance值


要更轻松地计算距离,您必须安装,正如您在标记中所建议的:

CREATE EXTENSION postgis;
该功能正是您所需要的,例如快速和肮脏:

WITH j AS (
  SELECT user_id, session_id, 
    max(timestamp ORDER BY timestamp),
    min(timestamp ORDER BY timestamp) 
  FROM trajectories t
  GROUP BY user_id,session_id  
) 
SELECT 
  s.user_id,s.session_id, 
  lat_start,lon_start, 
  lat_end,lon_end, 
  trip_starttime, 
  trip_endtime,
  age(trip_endtime,trip_starttime),
  ST_Distance(
    ST_MakePoint(lon_start,lat_start)::geography,
    ST_MakePoint(lon_end,lat_end)::geography) AS trip_distance
FROM 
  (SELECT 
    j.user_id, j.session_id, 
    t.timestamp AS trip_starttime,
    lat AS lat_start, lon AS lon_start FROM j
   JOIN trajectories t ON t.timestamp = j.min 
     AND t.session_id = j.session_id AND t.user_id = j.user_id) s,
  (SELECT 
    j.user_id, j.session_id, 
    t.timestamp AS trip_endtime,
    lat AS lat_end,lon AS lon_end FROM j
   JOIN trajectories t ON t.timestamp = j.max 
     AND t.session_id = j.session_id AND t.user_id = j.user_id) e
WHERE s.user_id = e.user_id AND s.session_id = e.session_id;

 user_id |   session_id   | lat_start | lon_start |  lat_end  |  lon_end   |     trip_starttime     |      trip_endtime      |   age    |  trip_distance   
---------+----------------+-----------+-----------+-----------+------------+------------------------+------------------------+----------+------------------
       1 | 20081023025304 | 39.984702 | 16.318417 | 39.984606 | 116.317065 | 2008-10-23 03:53:04+02 | 2008-10-23 03:53:50+02 | 00:00:46 | 8012597.30391588
另一方面:将经度和纬度存储在分开的列中几乎总是一个坏主意。如果可能,将它们存储到几何图形或地理列中。一开始这似乎是必要的,但PostGIS提供了大量的信息

进一步阅读:


将postgis添加到数据库中,然后阅读更多关于其中几何/地理功能的信息。您可以轻松计算距离st_distancegeom、geom或使用它将路径存储为单个记录。更多你会发现在这里添加到我的知识请,你能解释子查询s吗?我想知道您是如何访问t.timestamp、lat AS lat_start、lon AS lon_start FROM j的,子查询j只返回四个属性:user_id、session_id min/max timestamp。s和e子查询只匹配开始和结束记录的准确时间。我写这个连接是为了得到开始记录和结束记录的坐标。我使用j子查询的想法是获取所有的max和min值。这个问题是一个快速的解决方案,我相信减少它是可能的,但我想它给了你一个很好的开端,我明白了。我注意到的唯一问题是,对于具有大量GPS记录的用户,lat_start/end、lon_start/end从用户记录中获取的最大/最小lat/lon值不是开始/结束坐标,因此距离计算不准确。我注意到用户10在一次行程中超过8小时,但计算距离为123.731米。当我使用该用户的lat/lon开始/结束值进行检查时,该值是trip记录的最小值/最大值,而不是开始/结束坐标。用户10的8小时记录是否包含相同的会话id?是的,我可以确认它们具有相同的会话id。
WITH j AS (
  SELECT user_id, session_id, 
    max(timestamp ORDER BY timestamp),
    min(timestamp ORDER BY timestamp) 
  FROM trajectories t
  GROUP BY user_id,session_id  
) 
SELECT 
  s.user_id,s.session_id, 
  lat_start,lon_start, 
  lat_end,lon_end, 
  trip_starttime, 
  trip_endtime,
  age(trip_endtime,trip_starttime),
  ST_Distance(
    ST_MakePoint(lon_start,lat_start)::geography,
    ST_MakePoint(lon_end,lat_end)::geography) AS trip_distance
FROM 
  (SELECT 
    j.user_id, j.session_id, 
    t.timestamp AS trip_starttime,
    lat AS lat_start, lon AS lon_start FROM j
   JOIN trajectories t ON t.timestamp = j.min 
     AND t.session_id = j.session_id AND t.user_id = j.user_id) s,
  (SELECT 
    j.user_id, j.session_id, 
    t.timestamp AS trip_endtime,
    lat AS lat_end,lon AS lon_end FROM j
   JOIN trajectories t ON t.timestamp = j.max 
     AND t.session_id = j.session_id AND t.user_id = j.user_id) e
WHERE s.user_id = e.user_id AND s.session_id = e.session_id;

 user_id |   session_id   | lat_start | lon_start |  lat_end  |  lon_end   |     trip_starttime     |      trip_endtime      |   age    |  trip_distance   
---------+----------------+-----------+-----------+-----------+------------+------------------------+------------------------+----------+------------------
       1 | 20081023025304 | 39.984702 | 16.318417 | 39.984606 | 116.317065 | 2008-10-23 03:53:04+02 | 2008-10-23 03:53:50+02 | 00:00:46 | 8012597.30391588