这对于那些知道的人来说可能很简单(我希望!)
我有一个Oracle空间数据库,其中包含一个包含节点点列表的几何列,采用北/东格式(如果它是相关的!)
我需要选择落在给定点的给定半径范围内的那些对象。
Northings和Eastings相距1米,这使它更容易。
理想情况下,这应该包括跨越该区域的对象,即使它们的节点落在它之外。
这是一个简单的查询吗?也许使用SDO_WITHIN_DISTANCE?
表格如下:
MyTable
ID NUMBER
NAME VARCHAR2(20)
DESC VARCHAR2(50)
GEOM SDO_GEOMETRY
感谢您的帮助!
答案 0 :(得分:1)
您可以通过以下两种方式之一完成此操作。首先,正如您所提到的,SDO_WITHIN_DISTANCE是一种有效的方法。
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'
;
在这种情况下,距离是由空间参考定义的线性单位。 Oracle将坐标视为笛卡尔坐标,因此在使用此运算符之前需要确保您具有线性坐标系(而不是角度lat / lon单位)。既然你正在北方/东方工作,我认为只要你所比较的点在相同的空间参考中你就会没事。
如果你有很多要比较的点,这种方法使用内循环来解决查询,因此效率不高。此外,Oracle Spatial对SDO函数中操作数的顺序非常挑剔,因此您可能需要使用参数顺序来查找甜点。如果查询运行很长时间,请尝试切换sdo运算符的第一个和第二个参数。您还可以使用/*+ ORDERED */
之后的SELECT
后跟来播放“来自”和“内部联接”表格的顺序。
另一种方法是buffer the geometry并与缓冲区进行比较。
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'
;
请记住,SDO_RELATE的第二个参数(称为窗口)中的任何内容都不会有空间索引,如果你像我们在这里使用缓冲区那样进行变换。
如果您计划使用多个点进行此操作,建议构建一个表,其中缓冲所有源点。然后针对缓冲区域创建空间索引,并将其与目标点进行比较。
例如:
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'
;
注意:当与多边形相交的点时,您总是希望多边形位于sdo_relate的窗口位置(这是第二个参数)。这将确保正确使用您的空间索引。
答案 1 :(得分:1)
使用SDO_WITHIN_DISTANCE的正确方法,无论使用何种坐标系,无论是投影还是大地测量,都是如此:
select b.*
from my_table a, my_table b
where a.id = 1
and sdo_within_distance( b.shape, a.shape, 'distance=10 unit=meter' ) = 'TRUE';
空间谓词的参数顺序很重要:第一个是您要搜索的点,第二个是"查询窗口",即您要搜索的点。请注意,您应始终指定距离的单位 - 此处为10米。如果你没有,那么它将默认为你搜索的表的坐标系的单位。对于大地测量数据,它总是米。对于投影数据,它将是您坐标系的单位 - 通常也是米,但并非总是如此。明确指定一个单元可以解除所有歧义。
您也可以使用缓冲区方法,但这没有区别,实际上速度较慢。空间谓词的第二个参数是否被索引并不重要:不使用该索引。只需要使用 first 参数的索引。
要对几何集合执行操作 - 即对于一组点,找到每个点的设定距离内的点,然后考虑使用SDO_JOIN()函数,像这样找到所有几个点距离彼此不到10米:
SELECT a.id, b.id
FROM my_table a,
my_table b,
TABLE(SDO_JOIN(
'MY_TABLE', 'SHAPE',
'MY_TABLE', 'SHAPE',
'DISTANCE=10 UNIT=METER')
) j
WHERE j.rowid1 = a.rowid
AND j.rowid2 = a.rowid
AND a.rowid < a.rowid;