Запрос для выбора времени пересечения между точками и линией

#sql #postgresql #gis #postgis

Вопрос:

Я совсем новичок в postgis, и мне приходится запрашивать время, когда пользовательские дорожки пересекаются с линиями контрольных точек.

Мой дизайн БД :

 CREATE TABLE users (
  uuid UUID PRIMARY KEY,
  name VARCHAR(127) NOT NULL
);

CREATE TABLE locations (
  uuid UUID PRIMARY KEY,
  user_uuid UUID NOT NULL,
  location GEOMETRY(POINT) NOT NULL,
  located_at TIMESTAMP NOT NULL
);

CREATE TABLE checkpoints (
  uuid UUID PRIMARY KEY,
  line GEOMETRY(LINESTRING) NOT NULL
);
 

Я хотел бы построить запрос, который приведет к строкам такого типа :

 | checkpoint_uuid | user_uuid       | located_at          |
| --------------- | --------------- | ---------------     |
| checkpoint_1    | user_1          | 2021-11-05 15:50:30 |
| checkpoint_1    | user_2          | 2021-11-05 15:51:10 |
| checkpoint_1    | user_3          | 2021-11-05 15:51:13 |
| checkpoint_2    | user_1          | 2021-11-05 16:12:30 |
| checkpoint_2    | user_3          | 2021-11-05 16:13:41 |
| checkpoint_2    | user_2          | 2021-11-05 16:13:48 |
 

У меня есть несколько пользователей, которые отправляют данные о местоположениях с указанием времени в расположениях таблиц.
В таблице контрольных точек у меня есть строка для каждой контрольной точки. Пользователи когда-нибудь перейдут эти границы.

На данный момент я могу найти точку пересечения между пользовательским запуском и контрольными точками :

 SELECT checkpoints.uuid, user_uuid, ST_Intersection(ST_MakeLine("location")::geography, line)
FROM locations, checkpoints
GROUP BY checkpoints.uuid, user_uuid, line
 

Но я не могу восстановить время этого пересечения. Если я добавлю расположенное в к выбору, это приведет к сбою ГРУППЫ ПО

Ответ №1:

Если я правильно понял ваш вопрос, вам просто нужно пространственное соединение. С помощью этой функции ST_Intersects вы можете фильтровать только те записи, которые пересекаются, например

 SELECT 
  chk.uuid, 
  loc.user_uuid, 
  loc.located_at
FROM locations loc 
JOIN checkpoints chk ON ST_Intersects(loc.location,chk.line);
 

Комментарии:

1. Я только что попробовал это, но это не дает никаких результатов. На самом деле местоположения пользователей находятся не совсем на линии контрольной точки. Одна точка пользователя находится на один метр раньше, а следующая-на один метр позже. Пересечение должно быть между линией, проведенной всеми местоположениями пользователей, и линией контрольной точки.

2. @ybert будет ли буфер вокруг точки для вас вариантом?

3. @ybert не могли бы вы взглянуть на запрос в этой скрипке? Это может вас заинтересовать dbfiddle.uk/…

4. @ybert это действительно сложно. Альтернативой могло бы быть прямое обновление строки (добавление новых точек) вместо сохранения каждой новой точки отдельно в виде отдельной записи. Но поскольку я не знаком с вашим вариантом использования, он также может не применяться. Кроме того, вы должны использовать point m в этом отношении 😉 Ура и удачи

5. Я постараюсь сохранить прямую строку с указателем внутри. Спасибо, вы мне очень помогли ! 🙂