【问题标题】:Oracle Spatial - select objects falling within areaOracle Spatial - 选择区域内的对象
【发布时间】:2014-05-14 02:38:34
【问题描述】:

这对于知道的人来说可能很简单(我希望!)

我有一个 Oracle 空间数据库,其几何列包含节点点列表,采用北/东格式(如果相关!)

我需要选择那些落在给定点的给定半径内的对象。

北向和东向相距 1 米,这使它更容易一些。

理想情况下,这应该包括跨越该区域的对象,即使它们的节点点落在该区域之外。

这是一个简单的查询吗?也许使用 SDO_WITHIN_DISTANCE?

表格如下所示:

MyTable
ID NUMBER
NAME VARCHAR2(20)
DESC VARCHAR2(50)
GEOM SDO_GEOMETRY

感谢您的帮助!

【问题讨论】:

    标签: oracle oracle10g geospatial oracle-spatial


    【解决方案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'
    ;
    

    在这种情况下,距离采用由 a 的空间参考定义的线性单位。 Oracle 将坐标视为笛卡尔坐标,因此您需要确保在使用此运算符之前拥有一个线性坐标系(与角度纬度/经度单位相反)。由于您使用的是北/东,我认为只要您要比较的点在同一个空间参考中,您就可以了。

    这种方法使用内部循环来解决查询,因此如果您有很多要比较的点,则效率不高。此外,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 张桌子,我需要检查随机坐标。
    • 当然,只需在 sdo_relate 或 within_distance 运算符(这是第二个参数)的“窗口”位置生成形状。请注意,当您生成一个形状时,您并没有使用空间索引进行搜索,因此如果您开始遇到性能问题,您可能会考虑创建一个带有空间索引的表来保存您的几何图形。
    【解决方案2】:

    正确的方式使用 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;
    

    【讨论】:

      猜你喜欢
      • 2013-12-08
      • 2020-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-02
      • 2022-10-05
      • 2022-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多