1

我有一个包含 SDO_Geometries 的表,我查询所有几何图形以找到它们的起点和终点,然后将这些点插入另一个名为 ORAHAN 的表中。现在,我的主要目的是为 orahan 中的每个点提供 2 厘米缓冲区时,我必须确定它是否与 orahan 中的另一个点相交。所以我使用 Relate 和 Bufer 函数编写了一些 pl sql,但是当我检查 Map Info 中的一些记录时,我看到距离自身 1 厘米区域内有点,但在名为 ORAHANCROSSES 的交叉点表中没有记录。我是错误地使用了这些功能还是什么?

注意:我使用的是 Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production 和 PL/SQL Release 11.2.0.1.0 - 和 SDO_PACKAGE

ORAHAN 有大约 40 万条记录。(点和其他列。)

declare
BEGIN
 for curs in (select * from ORAHAN t) loop
   for curs2 in (select *
                   from ORAHAN t2
                  where SDO_RELATE(t2.geoloc,SDO_GEOM.SDO_BUFFER(curs.geoloc,0.02,0.5) , 
                  'mask=ANYINTERACT') = 'TRUE'
                    and t2.mi_prinx <> curs.mi_prinx) loop                    
     Insert INTO ORAHANCROSSES
     values
       (curs.Mip, curs.Startmi, curs2.Mip, curs2.Startmi);
     commit;
   end loop;
 end loop;
END;

这是 MapInfo 地图图像,显示了 3 个点,它们彼此接近 1 厘米。但是在 orahancrosses 中没有与这 3 个匹配的记录。

注:0,00001000km 等于 1cm 在此处输入图像描述

Orahan 元数据:

select * from user_sdo_geom_metadata where table_name = 'ORAHAN';

在此处输入图像描述

和暗信息:

在此处输入图像描述

4

1 回答 1

3

您的数据的坐标系是什么?而且,最重要的是,您在元数据中设置了什么容限?

其他一些评论:

1)不要使用与缓冲区相关的方法。只需使用距离内的方法。

2)对于这种查询,您不需要 PL/SQL 循环,只需使用简单的 CTAS:

create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from orahan c1, orahan c2
where sdo_within_distance (c2.geoloc, c1.geoloc, 'distance=2 unit=cm') = 'TRUE'
and c2.mi_prinx <> c1.mi_prinx;

3) 如前所述,在 2 cm 内的一对点 A 和 B 将被返回两次:一次为 (A,B),另一次为 (B,A)。为避免这种情况(并且只返回其中一种情况),请编写如下查询:

create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from orahan c1, orahan c2
where sdo_within_distance (c2.geoloc, c1.geoloc, 'distance=2 unit=cm') = 'TRUE'
and c1.rowid < c2.rowid;

3)处理您提到的点数(400000+)应该使用 SDO_JOIN 技术运行得更好,如下所示:

create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from  table (
        sdo_join (
          'ORAHAN','GEOLOC',
          'ORAHAN','GEOLOC',
          'DISTANCE=2 UNIT=CM'
        )
      ) j,
      orahan c1, 
      orahan c2
where j.rowid1 < j.rowid2
and c1.rowid = j.rowid1
and c2.rowid = j.rowid2;

这可能仍需要时间来处理 - 取决于您的数据库服务器的容量。如果您是 Oracle Enterprise Edition 的许可证并且您的硬件具有适当的容量(内核数),那么并行性可以减少经过的时间。

4)你说你使用的是Oracle 11g。什么确切版本?版本 11.2.0.4 是 11gR2 的终端版本。不再支持任何较旧的内容。现在你应该真的在 12cR1 (12.1.0.2) 上。在您的情况下,12.1.0.2 的主要好处是 Vector Performance Accelerator 功能,可加速许多空间功能和运算符(仅当您拥有适当的 Oracle Spatial 许可证时 - 免费的 Oracle Locator 功能不提供此功能)。

=======================================

在您的示例中使用两点。让我们计算距离:

select sdo_geom.sdo_distance(
  sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null), 
  sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.07336716,null),null,null),
  0.005
) distance
from dual;


  DISTANCE
----------
 .01000197

1 row selected.

请注意,我没有指定任何 SRID。假设坐标以米为单位,它们之间的距离确实有1厘米多一点。

=======================================

正如您所注意到的,您的原始语法不起作用的原因是您为 SDO_BUFFER() 调用指定的容差。您将其作为 0.5 (=50cm) 传递以生成半径为 0.02 (2cm) 的缓冲区。效果是产生的缓冲液有效地溶解到点本身。

例如在公差 0.5 处:

select sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.5) from dual;

产生:

SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(521554.782, 4230983.08, NULL), NULL, NULL)

在公差 0.005 处:

select sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.005) from dual;

你得到了正确的缓冲区:

SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 2), SDO_ORDINATE_ARRAY(521554.782, 4230983.06, 521554.802, 4230983.08, 521554.782, 4230983.1, 521554.762, 4230983.08, 521554.782, 4230983.06))

现在非常接近的点与该缓冲区匹配:

select sdo_geom.relate(
  sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.005),
  'determine',
  sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.07336716,null),null,null),
  0.005
) relation
from dual;

RELATION
------------------------- 
CONTAINS

1 row selected.

=======================================

现在,您的数据没有适当的显式 SRID 这一事实意味着在测量或基于距离的搜索中使用显式单位将不起作用。因为数据库不知道您的数据在哪个坐标系中,所以它不知道如何确定两个点之间的距离小于设定的 cm 或 m 数。您所能做的就是假设坐标以米为单位。

所以在我上面给出的例子中,替换'DISTANCE=2 UNIT=CM''DISTANCE=0.02'

于 2016-07-31T21:14:03.357 回答