0

我正在使用 SDO_NN 运算符来查找建筑物旁边最近的消火栓。

建造:

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

消火栓:

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

我已经为 building.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));
4

2 回答 2

0

为了在一个点和一个多边形之间进行空间比较,我们SDO_GEOMETRY定义了SDO_SRID=2001并且中心设置为SDO_POINT_TYPE->我们想要比较的 a。

MDSYS.SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(-79, 37, NULL), NULL, NULL)
于 2013-04-13T15:43:14.440 回答
0

首先,您的查询并不像您所说的那样:它实际上从您的任何消火栓返回最近的名为“汽车旅馆”的建筑物。为了做你想做的事(即相反),你需要将参数的顺序颠倒到 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.
于 2014-05-16T18:37:08.473 回答