日期:2014-05-17  浏览次数:20815 次

区域查询优化
假设有表记录点坐标信息如下
create table tbl_point(
PointID varchar(10), --点坐标编号
X numeric(8,2), --X坐标
Y numeric(8,2) --Y坐标
);

现在要求查询出表中属于某个任意多变形区域内的数据点记录;各位达人有什么高招没?
我采用的方法是,写一个函数,判断点point(x,y)是否在任意多边形区域polygon内。
create type point as object(
X numeric(8,2), --X坐标
Y numeric(8,2) --Y坐标 
);

create type polygon as table of point;

create function pointinpolygon(Apolygon polygon,Apoint point)
return boolean
as
begin
  ...
end;

然后在查询的时候使用语句
select * from tbl_point
where pointinpolygon(Apolygon,point(x,y)) ;

但这种方案明显效率偏低;
有没有更好的解决方式?

------解决方案--------------------
/*第一步,使用MDSYS.SDO_GEOMETRY类型标识控制点的坐标*/
create table tbl_point(
ID varchar(10),
Name varchar2(10),
XY MDSYS.SDO_GEOMETRY);

/第二步,填写xy坐标范围与精度/
insert into user_sdo_geom_metadata
values('tbl_point',
'xy',
MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X',-1000,1000,0.01),
MDSYS.SDO_DIM_ELEMENT('Y',-1000,1000,0.01)),
null
);
/*第三步,在xy字段上创建空间索引辅助对数据查询执行*/
create index tbl_point_index on tbl_point(xy) 
indextype is MDSYS.SPATIAL_INDEX;

/*第四步,插入空间数据*/
insert into tbl_point(ID,name,XY)
select 'KZD7101901','控制点01',
MDSYS.SDO_GEOMETRY(2001,null,MDSYS.SDO_POINT_TYPE(1,1,null),null,null) from dual union all
select 'KZD7101902','控制点02',
MDSYS.SDO_GEOMETRY(2001,null,MDSYS.SDO_POINT_TYPE(1,2,null),null,null) from dual union all
select 'KZD7101903','控制点03',
MDSYS.SDO_GEOMETRY(2001,null,MDSYS.SDO_POINT_TYPE(1,3,null),null,null) from dual union all
select 'KZD7101904','控制点04',
MDSYS.SDO_GEOMETRY(2001,null,MDSYS.SDO_POINT_TYPE(1,1,null),null,null) from dual union all
select 'KZD7101905','控制点05',
MDSYS.SDO_GEOMETRY(2001,null,MDSYS.SDO_POINT_TYPE(0,1,null),null,null) from dual;

/* 查询在多边形内的控制点数据并展示*/
declare
ARolygon MDSYS.SDO_GeomeTRY; --创建多边形
begin
AROLYGON := new MDSYS.SDO_GeomeTRY(2003,null,null,
MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1),
MDSYS.SDO_ORDINATE_ARRAY(0,0,0,1.5,2,1.5,2,0));
  
for myrecord in (
select a.ID,a.name,a.xy.SDO_POINT.x x坐标, a.xy.SDO_POINT.y Y坐标 
from tbl_point a
where MDSYS.SDO_RELATE(a.xy,AROLYGON,'mask=anyinteract querytype=window') = 'TRUE' ) 
loop
dbms_output.put_line(myrecord.ID||','||myrecord.name||','||myrecord.X坐标||','||myrecord.Y坐标);
end loop;
end;

--执行结果
KZD7101904,控制点04,1,1
KZD7101905,控制点05,0,1
KZD7101901,控制点01,1,1

------解决方案--------------------
帮顶!