Прежде всего, ваш запрос не делает того, о чем вы говорите: он на самом деле возвращает ближайшее здание под названием «Мотель» из любого из ваших гидрантов. Чтобы сделать то, что вы хотите (то есть наоборот), вам нужно изменить порядок аргументов на 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.
person
Albert Godfrind
schedule
16.05.2014