Oracle空间数据运算符 - SDO_nn - 未获得sdo_num_res = 1的任何结果

时间:2013-03-08 06:19:45

标签: spatial-query oracle-spatial

我正在使用SDO_NN操作员找到建筑物旁边最近的消防栓。

大厦:

CREATE TABLE  "BUILDINGS" 
(   
"NAME" VARCHAR2(40), 
"SHAPE" "SDO_GEOMETRY") 

消防栓:

CREATE TABLE  "HYDRANTS" 
   (    "NAME" VARCHAR2(10), 
"POINT" "SDO_POINT_TYPE"
  );

我已经为buildings.shape正确设置了空间索引,我运行查询以获取最近的建筑物'汽车旅馆'消防栓

select b1.name as name, h.point.x as x, h.point.y as y  from buildings b1, hydrants h where  b1.name ='Motel'  and
                    SDO_nn( b1.shape, MDSYS.SDO_GEOMETRY(2003,NULL, NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),
                            SDO_ORDINATE_ARRAY( h.point.x,h.point.y)), 'sdo_num_res=1')= 'TRUE';

问题在于:

当我设置参数 sdo_num_res = 1 时,我得到零元组。 当我使sdo_num_res = 2时,我得到一个元组。

这种怪异行为的原因是什么?

注意:我只在building.name ='Motel'时获得零行,对于所有其他元组,当sdo_num_res = 1时,我得到1行

编辑: 插入查询

Insert into buildings (NAME,SHAPE) values ('Motel',MDSYS.SDO_GEOMETRY(2003,NULL,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1),MDSYS.SDO_ORDINATE_ARRAY(564,425,585,436,573,458,552,447)));

Insert into hydrants  (name,POINT) values ('p57',MDSYS.SDO_POINT_TYPE(589,448,0));

2 个答案:

答案 0 :(得分:0)

要在点到多边形之间执行空间比较,SDO_GEOMETRY定义为SDO_SRID=2001,中心设置为SDO_POINT_TYPE->我们要比较。

MDSYS.SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(-79, 37, NULL), NULL, NULL)

答案 1 :(得分:0)

首先,您的查询不会按照您的说法执行操作:它实际上会返回最近的建筑,名为" Motel"从你的任何消防栓。要做你想做的事情(即相反)你需要颠倒SDO_NN的参数顺序:所有空间运算符使用第二个参数的值搜索第一个参数。

然后插入HYDRANTS表是错误的:

Insert into hydrants  (name,POINT) values ('p57',MDSYS.SDO_POINT_TYPE(589,448,0));

SDO_POINT_TYPE对象不是以这种方式使用的:它仅在SDO_GEOMETRY类型中使用。正确的方法是:

insert into hydrants (name,POINT) values ('p57',sdo_geometry(2001, null, SDO_POINT_TYPE(589,448,null), null, null));

当然,您需要相应地更改表格定义。

然后您的建筑物也被错误地创建:多边形必须始终关闭,即最后一个点必须与第一个点相同。所以正确的形状应该是这样的:

insert into buildings (NAME,SHAPE) values ('Motel', SDO_GEOMETRY(2003,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(564,425,585,436,573,458,552,447,564,425)));

以下是完整示例:

创建表格:

create table buildings (
  name varchar2(40) primary key,
  shape sdo_geometry
);

create table hydrants(
  name varchar2(10) primary key, 
  point sdo_geometry
);

填充表格:

insert into buildings (NAME,SHAPE) values ('Motel', SDO_GEOMETRY(2003,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(564,425,585,436,573,458,552,447,564,425)));
insert into hydrants (name,POINT) values ('p57',sdo_geometry(2001, null, SDO_POINT_TYPE(589,448,null), null, null));
commit;

确认几何图形都正确无误:

select name, sdo_geom.validate_geometry_with_context (point, 0.05) from hydrants;
select name, sdo_geom.validate_geometry_with_context (shape, 0.05) from buildings;

设置空间元数据并创建空间索引:

insert into user_sdo_geom_metadata (table_name, column_name, diminfo, srid)
values (
  'BUILDINGS',
  'SHAPE',
  sdo_dim_array (
    sdo_dim_element ('X', 0,1000,0.05),
    sdo_dim_element ('Y', 0,1000,0.05)
  ),
  null
);
commit;

create index buildings_sx on buildings (shape)
  indextype is mdsys.spatial_index;

insert into user_sdo_geom_metadata (table_name, column_name, diminfo, srid)
values (
  'HYDRANTS',
  'POINT',
  sdo_dim_array (
    sdo_dim_element ('X', 0,1000,0.05),
    sdo_dim_element ('Y', 0,1000,0.05)
  ),
  null
);
commit;

create index hydrants_sx on hydrants (point)
  indextype is mdsys.spatial_index;

现在尝试正确编写的查询:

select h.name, h.point.sdo_point.x as x, h.point.sdo_point.y as y  
from buildings b, hydrants h 
where b.name ='Motel' 
and sdo_nn(h.point, b.shape, 'sdo_num_res=1')= 'TRUE';

返回:

NAME                      X          Y
---------------- ---------- ----------
p57                     589        448

1 row selected.