我正在为北京市的人口流动性的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
). 我想使用此表中的原始数据将计算出的出行指标插入到一个新表中,我定义为:
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)
因为有些旅行跨越了城市。我在这里创建了一个db fiddle,其中包含该用户2次旅行的gps点(每个10点)。
我将感谢任何指导工作围绕这一点取得进展,在我目前的研究。
编辑
遇到这个函数可以用哈弗公式计算距离。我创建了这个函数,但我不知道如何使用它来获取 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;
1条答案
按热度按时间doinxwow1#
为了更容易地计算距离,您必须安装
PostGIS extension
,正如您在标签中所建议的:函数
ST_Distance
是您想要的,例如(快速和肮脏):另一方面:将经度和纬度存储在分开的列中几乎总是一个坏主意。如果可能,将它们存储到几何体或地理列中。一开始似乎很有必要,但postgis提供了大量的
kickass functions
!进一步阅读:
ST_MakePoint
Date/Time Functions