我有一个具有SDO_Geometries的表,我查询所有几何以找到它们的起点和终点,然后我将这些点插入到另一个名为ORAHAN的表中。现在我的主要目的是为了在orahan中的每个点我必须找到它是否与orahan中的另一个点相交时给点2 cm缓冲区。 所以我使用Relate和Bufer函数编写了一些pl sql,但是当我在Map Info中查看一些记录时,我看到距离自身1 cm区域内的点,但在交叉表中没有记录ORAHANCROSSES。 我错误地使用这些功能还是什么?
注意:我使用的是Oracle Database 11g企业版11.2.0.1.0版 - 64位生产版和 PL / SQL版本11.2.0.1.0 - 和SDO_PACKAGE
ORAHAN有大约400,000条记录。(点和其他列。)
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个匹配的记录。
Orahan元数据:
select * from user_sdo_geom_metadata where table_name = 'ORAHAN';
并且减少:
答案 0 :(得分:2)
您的数据的坐标系是什么?最重要的是,您在元数据中设置了什么容忍度?
其他一些评论:
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)如上所述,A点和B点在2厘米范围内的对将返回两次:一次为(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的主要优点是矢量性能加速器功能,它可以加速许多空间功能和操作员(仅当您拥有正确的Oracle Spatial许可证时 - 它才具有免费的Oracle定位器功能)。 / p>
======================================
使用示例中的两点。让我们计算距离:
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'