Postgres - вставить расстояние до ближайшего соседа в другую таблицу - PullRequest
0 голосов
/ 22 октября 2018

Итак, у меня есть три таблицы (A, B, C).В таблицах A и BI есть точки, и я хочу вставить в C каждую строку из A, а также некоторые столбцы из ближайшей точки от B до каждой точки в A, а также расстояние между ними.Я знаю, что запрос для получения ближайшего соседа выглядит следующим образом:

SELECT DISTINCT ON (A.id5) A.state, B.way, st_distance (A.geom,B.geom) INTO C
FROM A, B   
WHERE ST_DWithin(A.geom, B.geom, 150)    
ORDER BY A.objectid, ST_Distance(A.geom,A.geom)

Но мне нужно включить его в запрос INSERT большего размера, и я попытался сделать это следующим образом:

INSERT INTO complete(id_door, distance, id_way,Y, X, geom, check)
(SELECT A.state, (select distinct on (A.id5) ST_DISTANCE(A.geom,B.geom) from A order by A.id5, st_distance(A.geom,B.geom)), b.way, ST_Y(B.geom), ST_X(B.geom) ,B.geom, V.check
FROM A, B, C, V
WHERE
ST_INTERSECTS(A.geom, V.geom)\
AND ST_DWithin(A.geom, B.geom,150))

Но это не правильный путь, потому что я получаю ошибку:

psycopg2.ProgrammingError: more than one row returned by a subquery used as an expression

Я не могу скопировать все расстояния от А и В до С, а затем удалить все, кроме ближайшего, потому что это огромная таблицаи у меня не хватило бы памяти, поэтому мне нужен способ вставлять только строки с информацией из ближайшей точки от B до A.

Что я здесь не так делаю?Заранее спасибо

ОБНОВЛЕНИЕ:

После некоторой помощи я узнал, что должен использовать Lateral в запросе Select, но я не уверен, какиспользуй это.

Мне нужен метод Select, чтобы получить каждую строку в таблице A и найти ближайшего соседа из таблицы B, что, как я полагаю, сделано с помощью ранее указанного запроса, и вставить в таблицу C некоторые столбцы из A, некоторые столбцыот ближайшего соседа (таблица B) и некоторых столбцов из таблицы V, которая выбирается условием пересечения.Основная проблема в том, как организовать все это в Select, чтобы я не получил ошибку.

Вот где я сейчас нахожусь:

INSERT INTO C (id_door, distance, id_way,Y, X, geom, check)
(SELECT A.state, l.*, V.check
FROM A, B, C, V
lateral (select st_distance(a.geom,b.geom),  b.way, ST_Y(B.geom), ST_X(B.geom) ,B.geom
From B 
Where ST_DWithin(a.geom, b.geom,150))
Order by a.geom<->b.geom limit 1) l
WHERE
ST_INTERSECTS(A.geom, V.geom)

1 Ответ

0 голосов
/ 22 октября 2018

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

Insert into C (id_door, distance, id_way,Y, X, geom, check)
select l.*
  from a,
  lateral (select a.state, st_distance(a.geom,b.geom),
                  b.way, ST_Y(B.geom), ST_X(B.geom), B.geom,
                  v.check
             from b, v
            where ST_DWithin(a.geom, b.geom,150)
              and st_dwithin(a.geom,v.geom,0)
              and st_intersects(a.geom,v.geom)
            order by a.geom<->b.geom, v.geom limit 1) l

Если вам нужно больше записей на каждую точку от A, увеличьте предел с 1 доВаше желаемое значение.

...