我正在寻找以下问题的解决方案: 我在postgress 9.3中有数千个点功能表。我想摆脱微不足道的一点。通过微不足道的我理解的点不是很多邻居,可以通过距离或扩展的bbox来定义。我最好算一下这些邻居,然后决定它们的数量是多少。欢迎任何建议!
答案 0 :(得分:1)
最简单的方法是使用空间自连接来计算一个表中与另一个表中每个点的缓冲区相交的点数(两个表都相同,也就是说,你正在研究笛卡尔积,尽管这可以通过空间索引得到缓解 - 见下文。假设您有一个名为points的表,并且您的点数字段称为geom,并且每个点都有一个ID字段,并且您对每个点内的所有点感兴趣,比如每个点1km,您会这样做:
select a.id, count(b.id) as num_neighbors
from
points a, points b
where st_dwithin(a.geom, b.geom, 1000) and a.id != b.id
group by a.id
order by num_neighbors;
使用order by和limit x查找邻居数最少的x点。
如果要使用矩形区域而不是圆形区域来计算neigbors的数量,请使用ST_Expand函数(与ST_Intersects结合使用)而不是ST_DWithin。但是,由于ST_DWithin直接使用索引,因此速度较慢,准确度较低。
对于非常重要的表格大小的表现原因,请确保您的几何字段上有spatial index。
编辑2 :在您的问题更新后,我建议您尝试此方法,遵循Postgres用于子查询更新的更新,设置,发布,顺序
update point SET num_neighbors=agg.num_neighbors
from (
select count(b.id) as num_neighbors, a.id
from
point a, point b
where st_dwithin(a.geom, b.geom, 1000) and a.id != b.id group by a.id)
agg
where agg.id=point.id;
在此查询前使用explain
,并将预期的执行时间与您拥有的查询进行比较。我没有确切的数据,但是通过一组随机点测试,此查询的速度比您在更新后的问题中的速度快了几个数量级。
编辑1:根据Mike T的建议,编辑原始答案以考虑使用ST_DWithin的更好方法。
答案 1 :(得分:0)
@John因为我需要在我的源表中存储结果我稍微修改了你的语句(因为我只是SQL中的初学者,它可能有点孩子气):
UPDATE point SET num_neighbors =(
select count(b.id) as num_neighbors from
point a, point b
where st_dwithin(a.geom, b.geom, 100) and a.id != b.id and a.id=point.id
group by a.id);
大约需要200s才能获得~85k的记录,这是可以接受的但不是欣喜若狂(没有gist指数,它比恐龙成为汽油需要更长的时间)。如果你看到任何方法来加速它(甚至损害一些准确性)那将是非常棒的!。
问候 托马斯