gpt4 book ai didi

oracle - SDO_INSIDE 返回零记录

转载 作者:行者123 更新时间:2023-12-02 01:32:18 36 4
gpt4 key购买 nike

所以我有一个餐 table 村:

CREATE TABLE village (
building_id integer PRIMARY KEY,
name VARCHAR2(30),
visitors integer,
building SDO_GEOMETRY
);

和一个表访客:
create table visitors(
id integer,
position SDO_GEOMETRY
);

以下是插页:
INSERT INTO village VALUES(2,'KircheV2', 4,
SDO_GEOMETRY(
2003,
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,1),
SDO_ORDINATE_ARRAY(100,100, 100,120, 120,100, 120,120)
)
);


INSERT INTO visitors VALUES (1,
SDO_GEOMETRY(
2001,
NULL,
SDO_POINT_TYPE(110, 110, NULL),
NULL,
NULL
)
);

出于某种原因,当我尝试获取“KircheV2”内部的所有访问者时,SQL 语句总是返回零记录:
SELECT * FROM visitors,village WHERE village.name like 'KircheV2' and (SDO_INSIDE(village.building,visitors.POSITION) = 'TRUE');

背后的原因是什么?坐标 110;110 实际上应该在建筑物的中间,所以它应该在建筑物内部。

最佳答案

你的数据不正确。您可以像这样验证它:

SQL> select sdo_geom.validate_geometry_with_context (building,0.005) from village;

SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(BUILDING,0.005)
-------------------------------------------------------------------------------
13348 [Element <1>] [Ring <1>]

1 row selected.

该错误意味着:
ORA-13348: polygon boundary is not closed

在 Oracle(实际上是所有存储系统)中,根据 OGC 规则,多边形必须闭合,即第一个顶点必须作为最后一个顶点重复。所以:
INSERT INTO village VALUES(2,'KircheV2', 4,
SDO_GEOMETRY(
2003,
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,1),
SDO_ORDINATE_ARRAY(100,100, 100,120, 120,100, 120,120, 100,100)
)
);

但是选择仍然无法返回任何结果。这是为什么 ?
SQL> select sdo_geom.validate_geometry_with_context (building,0.005) from village;

SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(BUILDING,0.005)
-------------------------------------------------------------------------------
13349 [Element <1>] [Ring <1>][Edge <2>][Edge <4>]

1 row selected.

此错误意味着:
ORA-13349: polygon boundary crosses itself

这是有道理的:顶点显然形成了蝴蝶形状:

100,100, 100,120, 120,100, 120,120, 100,100

假设你想形成一个简单的矩形,那么正确的形状是:

100,100, 100,120, 120,120, 120,100, 100,100
INSERT INTO village VALUES(2,'KircheV2', 4,
SDO_GEOMETRY(
2003,
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,1),
SDO_ORDINATE_ARRAY(100,100, 100,120, 120,120, 120,100, 100,100)
)
);

还是没有结果。为什么 ?
SQL> select sdo_geom.validate_geometry_with_context (building,0.005) from village;

SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(BUILDING,0.005)
-------------------------------------------------------------------------------
13367 [Element <1>] [Ring <1>]

1 row selected.

这表示:
ORA-13367: wrong orientation for interior/exterior rings

多边形中的环必须正确定向。外圈必须逆时针,内圈(孔)必须顺时针。所以你需要这样写:

100,100, 120,100, 120,120, 100,120, 100,100
INSERT INTO village VALUES(2,'KircheV2', 4,
SDO_GEOMETRY(
2003,
NULL,
NULL,
SDO_ELEM_INFO_ARRAY(1,1003,1),
SDO_ORDINATE_ARRAY(100,100, 120,100, 120,120, 100,120, 100,100)
)
);

还是没有结果!但那是因为您的查询表述不正确。 SDO_INSIDE(a,b)查找完全在 B 内部的所有 A。在您的情况下,这就像询问访客内部的建筑物。显然你想要相反,所以要么说: SDO_INSIDE(visitor, building) SDO_CONTAINS (building,visitor) , 像这样:
SELECT * FROM visitors,village WHERE village.name like 'KircheV2' and SDO_INSIDE(visitors.POSITION,village.building) = 'TRUE';
SELECT * FROM visitors,village WHERE village.name like 'KircheV2' and SDO_CONTAINS(village.building,visitors.POSITION) = 'TRUE';

一些额外的评论:
  • 你的例子纯属人为,我想?在现实生活中,您的多边形将来自某些 GIS 系统 - 例如您加载到数据库中的 ESRI shapefile,或从某些 GIS 工具捕获的形状。无论哪种方式,两者都会产生正确的形状,因为所有工具都适用于形状闭合和方向的 OGC 规则。如果不是,验证函数会告诉你错误,sdo_util.rectify_geometry功能将纠正基本错误。
  • 您还需要了解空间运算符(INSIDE vs CONTAINS 等)及其效果。该文档解释了它们的含义。请注意,SDO_xxx 运算符集与 OGC 定义的 ST_xxx 函数略有不同。
  • 您不指定任何坐标系(SDO_SRID 为 NULL)。虽然这在您的人工示例中有效,但在现实生活中您应该始终使用正确的坐标系。特别是如果您的形状是大地测量的(长/纬度),您必须使用正确的 SRID:4326 来说明。这保证了所有计算都是在地球的椭圆体形状的范围内完成的。如果您要执行基于距离的查询或测量长度、距离或面积,这一点尤其重要。对投影数据使用正确的 SRID 同样重要。无论使用何种坐标系,它都可以让您执行查询:例如,查找 GPS 点所在的地 block (在本地投影中)。
  • 性能和索引。确保您有空间索引。虽然 Oracle 12.2 允许您在不定义索引的情况下进行查询,但以前的版本总是需要一个(如果不存在则失败)。如果该表甚至中等大,则对没有空间索引的表执行查询可能会非常慢。例如,以您的村庄和游客为例。假设您想从包含 1000 万访客的表格中找出特定建筑物中的所有访客。在访问者表上没有任何索引的情况下,数据库将需要将每个访问者与所选建筑物进行比较。这在 CPU 上会很昂贵(I/O 不是真正的问题)。
  • 最后,正确编写查询很重要。在像 F(a,b) 这样的运算符中, b用于搜索a所以b应该是较小的集合。例如,查找该建筑物中的所有访客必须写为 SDO_INSIDE(visitors, buildings) .反过来(这个客户在哪栋楼里?)写成 SDO_CONTAINS(buildings, visitors) .
  • 关于oracle - SDO_INSIDE 返回零记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49678279/

    36 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com