Я работаю с наборами данных 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 выше показывает последовательность точек GPS для 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 здесь , содержащий точки GPS для 2 поездок для этого пользователя (по 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;