Oracle
 sql >> Database >  >> RDS >> Oracle

Oracle Spatial:seleziona gli oggetti che rientrano nell'area

Puoi farlo in due modi. Innanzitutto, come hai menzionato, SDO_WITHIN_DISTANCE è un approccio valido.

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'
;

In questo caso, la distanza è in unità lineari definite dal riferimento spaziale di a. Oracle tratta le coordinate come cartesiane, quindi dovrai assicurarti di avere un sistema di coordinate lineare prima di utilizzare questo operatore (al contrario delle unità angolari lat/lon). Dal momento che stai lavorando con nord/est, penso che andrà bene purché i punti con cui stai confrontando siano nello stesso riferimento spaziale.

Questo approccio utilizza un ciclo interno per risolvere la query, quindi non è molto efficiente se hai molti punti con cui confrontare. Inoltre, Oracle Spatial è MOLTO esigente riguardo all'ordine degli operandi nelle funzioni SDO, quindi potrebbe essere necessario giocare con l'ordine dei parametri per trovare lo sweetspot. Se la tua query viene eseguita per un lungo periodo, prova a cambiare il primo e il secondo parametro del tuo operatore sdo. Puoi anche giocare con l'ordine dei tavoli 'from' e 'inner join' usando il /*+ ORDERED */ dietro SELECT .

Un altro approccio consiste nel bufferizzare la geometria e confrontalo con il 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'
;

Tieni presente che qualunque cosa sia nel secondo parametro di SDO_RELATE (chiamato finestra) non avrà un indice spaziale se lo trasformi come se fossimo qui con il buffer.

Se si prevede di eseguire questa operazione con più punti, si consiglia di creare una tabella in cui tutti i punti di origine sono memorizzati nel buffer. Quindi crea un indice spaziale rispetto alle aree bufferizzate e confrontalo con i tuoi punti target.

Ad esempio:

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:quando si intersecano punti con poligoni, si desidera che il poligono sia sempre nella posizione della finestra di sdo_relate (che è il secondo parametro). Ciò garantirà che il tuo indice spaziale venga utilizzato correttamente.