我正在使用北京城市人口流动的GPS数据集。在我的原始GPS表中,trajectories
是所有用户的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查询显示了user 1
从当前行程(session_id=20081023025304
)的起点到的GPS点的顺序。我想使用此表中的原始数据将计算出的行程指标插入到我定义为的新表中:
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 | | |
+---------+----------------+-----------+-----------+------------+------------+------------------------+------------------------+---------------+---------------+
用的值trip_duration
和trip_distance
计算出的(当然的值trip_duration
将是trip_endtime - trip_starttime
)。
我一直停留在我的研究为思考如何做到这一点在一两天的PostgrSQL
数据库过滤只有北京全市范围内旅行latitude (39.85 - 40.05)
,并longitude (116.25 - 116.5)
作为跨越超越了城市一些行程。我在这里创建了一个分贝提琴,其中包含该用户2次旅行的GPS点(每个点10点)。
我将不胜感激任何指南,以解决此问题,以使我目前的研究取得进展。
编辑
碰到这个函数,使用Haversine公式计算距离。我创建了此函数,但不确定如何使用它来获取trip_distance
价值。
CREATE OR REPLACE FUNCTION distance(
lat1 double precision,
lon1 double precision,
lat2 double precision,
lon2 double precision)
RETURNS double precision AS
$BODY$
DECLARE
R integer = 6371e3; -- Meters
rad double precision = 0.01745329252;
φ1 double precision = lat1 * rad;
φ2 double precision = lat2 * rad;
Δφ double precision = (lat2-lat1) * rad;
Δλ double precision = (lon2-lon1) * rad;
a double precision = sin(Δφ/2) * sin(Δφ/2) + cos(φ1) * cos(φ2) * sin(Δλ/2) * sin(Δλ/2);
c double precision = 2 * atan2(sqrt(a), sqrt(1-a));
BEGIN
RETURN R * c;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
为了更轻松地计算距离,您必须按照PostGIS extension
标记中的建议安装,方法是:
CREATE EXTENSION postgis;
该函数ST_Distance
是您要查找的内容,例如(快速&肮脏):
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确实提供了很多功能kickass functions
!
进一步阅读:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句