Sql 如何根据这些表中的空间关系几何图形将数据从一个表设置到另一个表
我有两个数据表。我需要根据这些表中数据之间的空间关系将数据构建从一个表设置到另一个表。源表中的空间数据为多边形类型,目标表中的空间数据为点。我查询了相交的点和多边形。很好用。但也有一些点与多边形不相交。我的想法是为这些点中的每一个定义最近的多边形,并从中获取建筑物的值。为此,我编写了一个函数,它获取点的id并返回building_h值。在测试中,它工作正常Sql 如何根据这些表中的空间关系几何图形将数据从一个表设置到另一个表,sql,postgresql,postgis,Sql,Postgresql,Postgis,我有两个数据表。我需要根据这些表中数据之间的空间关系将数据构建从一个表设置到另一个表。源表中的空间数据为多边形类型,目标表中的空间数据为点。我查询了相交的点和多边形。很好用。但也有一些点与多边形不相交。我的想法是为这些点中的每一个定义最近的多边形,并从中获取建筑物的值。为此,我编写了一个函数,它获取点的id并返回building_h值。在测试中,它工作正常 CREATE OR REPLACE FUNCTION closest_pol(int4) RETURNS NUMERIC AS $$ DE
CREATE OR REPLACE FUNCTION closest_pol(int4)
RETURNS NUMERIC
AS
$$
DECLARE
retVal NUMERIC;
BEGIN
SELECT bgs.building_h INTO retVal
FROM buildings_geoalert_spgg bgs, building_from_landuse_spgg bfl
WHERE ST_INTERSECTS(bgs.geom, ST_BUFFER(bfl.geom_centr, 0.0006,'quad_segs=8')) AND bfl.id = $1
ORDER BY ST_INTERSECTION(bgs.geom, ST_BUFFER(bfl.geom_centr, 0.0006,'quad_segs=8')) ASC
LIMIT 1;
RETURN retVal;
END;
$$
LANGUAGE plpgsql
STABLE
RETURNS NULL ON NULL INPUT;
但是,当我对整个表运行查询时,它将永远执行。。(对于约3000行,具有空值)。它持续了好几个小时才停下来
UPDATE building_from_landuse_spgg AS bfl SET
building_h = (SELECT closest_pol(bfl.id))
WHERE bfl.building_h IS NULL;
你知道我做错了什么吗?在你的
WHERE
子句中,你使用的ST_与查询时间内创建的0.006缓冲区相交。考虑使用您的这个缓冲区使用部分<代码> GIST< /代码>索引(如果出于任何原因,您必须使用它们):
我认为不需要函数,因为可以在UPDATE
语句中将函数内部的查询用作子查询。但是如果您有坚持使用该函数的理由,您可以取消选择来调用它:
UPDATE building_from_landuse_spgg
SET building_h = closest_pol(id)
WHERE building_h IS NULL;
编辑:正如@JGH正确提到的(参见注释),使用缓冲区比简单地使用缓冲区效率低。因此,如果您负担得起,请在WHERE
子句中使用的几何图形中创建索引
CREATE INDEX idx_landuse_geom_centr ON building_from_landuse_spgg USING gist (geom_centr);
CREATE INDEX idx_geoalert_geom ON buildings_geoalert_spgg USING gist (geom);
。。此外,部分索引building_h
会加快速度,因为您只对NULL
记录感兴趣:
CREATE INDEX idx_landuse_building_h ON building_from_landuse_spgg (building_h)
WHERE building_h IS NULL;
或者,如果您喜欢更广泛的索引,但仍然将NULL
值放在第一个类中
并且可能考虑将函数的代码放在子查询中,例如
UPDATE building_from_landuse_spgg AS bfl
SET building_h = (
SELECT bgs.building_h
FROM buildings_geoalert_spgg bgs
WHERE ST_DWithin(bgs.geom, bfl.geom_centr, 0.0006)
ORDER BY ST_Distance(bgs.geom, bfl.geom_centr) ASC LIMIT 1)
WHERE bfl.building_h IS NULL;
进一步阅读:
您能添加两个查询的解释吗?不要使用缓冲区,而是st_dwithin
。不要按交叉点排序,而是按距离排序使用st_dwithin
将更有效,并将导致更准确的结果,因为缓冲区只是一个近似值。@JGH我完全同意。我只是坚持在OP中使用的函数,但你是对的。。圣德维辛是一个更好的选择:)干杯
CREATE INDEX idx_landuse_building_h ON building_from_landuse_spgg
(building_h NULLS FIRST);
UPDATE building_from_landuse_spgg AS bfl
SET building_h = (
SELECT bgs.building_h
FROM buildings_geoalert_spgg bgs
WHERE ST_DWithin(bgs.geom, bfl.geom_centr, 0.0006)
ORDER BY ST_Distance(bgs.geom, bfl.geom_centr) ASC LIMIT 1)
WHERE bfl.building_h IS NULL;