Ближайший сосед и расстояние между точками и линиями - PullRequest
0 голосов
/ 26 сентября 2019

В Oracle Spatial у меня есть две таблицы ( AVALREGULACAO и ATROCOADUTOR ), представляющие точки и линии соответственно.

Структура обеих таблиц следующая:

AVALREGULACAO ( 295 точечных записей )
IPID [число (10)]
ГЕОМЕТРИЯ [MDSYS.SDO_GEOMETRY] ​​

ATROCOADUTOR ( 12536 записей строк)
IPID [число (10)]
ГЕОМЕТРИЯ [MDSYS.SDO_GEOMETRY] ​​

Мне нужно найти ближайшего соседа ATROCOADUTOR от каждого AVALREGULACAO и вычислить расстояние между ними

AVALREGULACAO_IPID |ATROCOADUTOR _IPID |РАССТОЯНИЕ

Я использовал 2 варианта

1

SELECT /*+ ORDERED */ A.IPID, B.IPID, MIN(SDO_GEOM.SDO_DISTANCE(sdo_cs.make_2d(A.GEOMETRY), sdo_cs.make_2d(B.GEOMETRY), 0.005)) as DISTANCE
FROM AVALREGULACAO A, ATROCOADUTOR B 
GROUP BY c_b.IPID,c_d.IPID;

Это занимает довольно много времени для вычисления - генерируетогромный выход 295 x 12536 = 3 698 120 возможных комбинаций (декартово произведение).Кроме того, выходной файл CSV не может вместить все эти записи (ограничение 1 048 576 строк)

Мне нужно только 295 записей, соответствующих 295 AVALREGULACAO.

2
Я также пробовал / адаптировал другой запрос с оператором ближайшего соседа (nn)

PROMPT IPID, nearest_IPID, distance  
  select /*+ ORDERED USE_NL(s,s2)*/
         s.IPID,
         s2.IPID as nearest_IPID,
         TO_CHAR(REPLACE(mdsys.sdo_geom.sdo_distance(sdo_cs.make_2d(s.GEOMETRY),sdo_cs.make_2d(s2.GEOMETRY),0.05), ',','.')) as distance
    from AVALREGULACAO s,
         ATROCOADUTOR s2
   where s2.IPID in (select IPID
                from AVALREGULACAO s3
               where sdo_nn(s3.GEOMETRY,s.GEOMETRY,'sdo_batch_size=10',1) = 'TRUE'
                       and s3.IPID <> s.IPID
                       and rownum < 2)
 order by 1,2;

Этот запрос занимает вечность - мне нужно остановить процесс до его завершения.

Я думаюМне не хватает того, как оптимизировать / отфильтровать желаемые результаты.

Буду признателен за любые советы по эффективному решению этой проблемы.

Заранее спасибо, Педро

PS: @Boneist.Большое спасибо за ввод.

К сожалению, я получил ошибку после применения вашего запроса (все еще пытаюсь работать с семантикой / синтаксисом новых команд KEEP, dens_rank)

SELECT a.ipid a_ipid,
       MIN(b.ipid) KEEP (dense_rank FIRST order by sdo_nn(a.GEOMETRY,b.GEOMETRY,'sdo_batch_size=10',1)) b_ipid,
       MIN(sdo_geom.sdo_distance(sdo_cs.make_2d(a.geometry), sdo_cs.make_2d(b.geometry), 0.005)) AS distance
FROM   avalregulacao a
       INNER JOIN atrocoadutor b ON sdo_nn(a.GEOMETRY,b.GEOMETRY,'sdo_batch_size=10',1) = 'TRUE'
GROUP  BY a.ipid;

Ошибка

Error starting at line : 1 in command -
SELECT a.ipid a_ipid,
MIN(b.ipid) KEEP (dense_rank FIRST order by sdo_nn(a.GEOMETRY,b.GEOMETRY,'sdo_batch_size=10',1)) b_ipid,
MIN(sdo_geom.sdo_distance(sdo_cs.make_2d(a.geometry), sdo_cs.make_2d(b.geometry), 0.005)) AS distance 
FROM avalregulacao a 
INNER JOIN atrocoadutor b ON sdo_nn(a.GEOMETRY,b.GEOMETRY,'sdo_batch_size=10',1) = 'TRUE'
GROUP  BY a.ipid
Error at Command Line : 2 Column : 45
Error report -
SQL Error: ORA-29907: foram encontradas etiquetas em duplicado em invocações primárias
29907. 00000 -  "found duplicate labels in primary invocations"
*Cause:    There are multiple primary invocations of operators with
           the same number as the label.
*Action:   Use distinct labels in primary invocations.

1 Ответ

0 голосов
/ 26 сентября 2019

Я думаю, что вы, вероятно, после чего-то вроде:

SELECT a.ipid a_ipid,
       MIN(b.ipid) KEEP (dense_rank FIRST order by sdo_nn(a.GEOMETRY,b.GEOMETRY,'sdo_batch_size=10',1)) b_ipid,
       MIN(sdo_geom.sdo_distance(sdo_cs.make_2d(a.geometry), sdo_cs.make_2d(b.geometry), 0.005)) AS distance
FROM   avalregulacao a
       INNER JOIN atrocoadutor b ON sdo_nn(a.GEOMETRY,b.GEOMETRY,'sdo_batch_size=10',1) = 'TRUE'
GROUP  BY a.ipid;

Это объединяет обе таблицы в функции ближайшего соседа, что должно уменьшить количество возвращаемых строк.

The MIN(b.ipid) KEEP (dense_rank first order by sdo_nn(a.GEOMETRY,b.GEOMETRY,'sdo_batch_size=10',1)) просто возвращает самое низкое значение b.ipid для наименьшей разности.

(Я думаю, что этот запрос будет работать как есть, но я не могу его проверить. Возможно, вам придется выполнить объединение и получить sdo_nn(a.GEOMETRY,b.GEOMETRY,'sdo_batch_size=10',1) как столбец в подзапросе, а затем выполните группировку во внешнем запросе.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...