Oracle
 sql >> Base de données >  >> RDS >> Oracle

Oracle Spatial - sélectionnez les objets tombant dans la zone

Vous pouvez faire celui-ci de deux manières. Tout d'abord, comme vous l'avez mentionné, SDO_WITHIN_DISTANCE est une approche valable.

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

Dans ce cas, la distance est en unités linéaires définies par la référence spatiale de a. Oracle traite les coordonnées comme cartésiennes, vous devrez donc vous assurer que vous disposez d'un système de coordonnées linéaires avant d'utiliser cet opérateur (par opposition aux unités angulaires lat/lon). Puisque vous travaillez avec des ordonnées/abscisses, je pense que tout ira bien tant que les points que vous comparez sont dans la même référence spatiale.

Cette approche utilise une boucle interne pour résoudre la requête, donc pas très efficace si vous avez beaucoup de points à comparer. De plus, Oracle Spatial est TRÈS pointilleux sur l'ordre des opérandes dans les fonctions SDO, vous devrez donc peut-être jouer avec l'ordre des paramètres pour trouver le sweetspot. Si votre requête s'exécute pendant une longue période, essayez de changer le premier et le deuxième paramètre de votre opérateur sdo. Vous pouvez également jouer avec l'ordre des tables 'from' et 'inner join' en utilisant le /*+ ORDERED */ hind après SELECT .

Une autre approche consiste à buffer la géométrie et comparer avec le tampon.

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

Gardez à l'esprit que tout ce qui se trouve dans le deuxième paramètre du SDO_RELATE (appelé la fenêtre) n'aura pas d'index spatial si vous le transformez comme si nous étions ici avec le tampon.

Si vous envisagez de le faire avec plusieurs points, il est recommandé de créer une table dans laquelle tous les points source sont mis en mémoire tampon. Créez ensuite un index spatial par rapport aux zones tamponnées et comparez-le à vos points cibles.

Par exemple :

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

REMARQUE :lorsque vous croisez des points avec des polygones, vous souhaitez toujours que le polygone soit dans la position de la fenêtre du sdo_relate (qui est le deuxième paramètre). Cela garantira que votre index spatial est utilisé correctement.