Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle Spatial - selecione objetos dentro da área


Você pode fazer isso de duas maneiras. Primeiro, como você mencionou, SDO_WITHIN_DISTANCE é uma abordagem válida.
select 
    *
from center_point a
inner join target_points b
    on a.id = 1
    and sdo_within_distance( b.shape, a.shape, 'distance = 10' ) = 'TRUE'
;

Neste caso, a distância está em unidades lineares definidas pela referência espacial de a. O Oracle trata as coordenadas como cartesianas, portanto, você precisará certificar-se de ter um sistema de coordenadas lineares antes de usar este operador (em oposição às unidades angulares de latitude/longitude). Como você está trabalhando com nortes/lestes, acho que você ficará bem desde que os pontos com os quais você está comparando estejam na mesma referência espacial.

Essa abordagem usa um loop interno para resolver a consulta, portanto, não é muito eficiente se você tiver muitos pontos para comparar. Além disso, o Oracle Spatial é MUITO exigente quanto à ordem dos operandos nas funções SDO, então você pode precisar brincar com a ordem dos parâmetros para encontrar o sweetspot. Se sua consulta for executada por um longo período, tente alternar o primeiro e o segundo parâmetro do seu operador sdo. Você também pode jogar com a ordem das tabelas 'de' e 'junção interna' usando o /*+ ORDERED */ hind após SELECT .

Outra abordagem é proteger a geometria e comparar com o buffer.
select 
    *
from center_point a
inner join target_points b
    on a.id = 1
    and sdo_relate( b.shape, sdo_buffer(a.shape, 0.05 ), 'mask=anyinteract' ) = 'TRUE'
;

Tenha em mente que o que estiver no segundo parâmetro do SDO_RELATE (chamado de janela) não terá um índice espacial se você o transformar como estamos aqui com o buffer.

Se você planeja fazer isso com vários pontos, é recomendável construir uma tabela onde todos os pontos de origem sejam armazenados em buffer. Em seguida, crie um índice espacial em relação às áreas protegidas e compare-o com seus pontos de destino.

Por exemplo:
create table point_bufs unrecoverable as
select sdo_buffer (a.shape, b.diminfo, 1.35)
from centerpoint a, user_sdo_geom_metadata b
where table_name='CENTERPOINT'
  and column_name='SHAPE';

select
    a.gif,
    b.gid 
from target_points a, 
     point_bufs b
where sdo_relate(a.shape, b.shape, 'mask=anyinteract querytype=join') = 'TRUE'
;

NOTA:Ao cruzar pontos com polígonos, você sempre deseja que o polígono esteja na posição da janela do sdo_relate (que é o segundo parâmetro). Isso garantirá que seu índice espacial seja usado corretamente.