我正在尝试向一系列美国县多边形添加“基于人口的质心”列,其中位置不是基于多边形的地理质心,而是基于地名填充地点的位置人口最多。例如,我想将箭头指示的点的几何形状(点直径=人口)分配给所选多边形的基于人口的质心列:
我已经测试了此查询,它返回任何给定多边形(例如波士顿萨福克县)的正确几何图形:
SELECT g1.the_geom
FROM counties c1
JOIN geonames g1
ON ST_Contains(c1.the_geom, g1.the_geom)
WHERE c1.name = 'Suffolk County, MA'
ORDER BY g1.population DESC
LIMIT 1;
但是,我正在处理大约 4000 个多边形,当我尝试在像这样的 UPDATE 函数中使用查询时,它会无限期地挂起(或者至少比对于这么多功能应有的时间要长得多):
UPDATE counties
SET the_geom_popcentroid = (
SELECT g1.the_geom
FROM counties c1
JOIN geonames g1
ON ST_Contains(c1.the_geom, g1.the_geom)
ORDER BY g1.population DESC
LIMIT 1
);
我在哪里错误地嵌套了这个 UPDATE 函数?
最佳答案
仔细检查:由于外表中的每一行与相关子查询的结果之间没有任何联系,因此您会得到每个的常量值em> 行。令人费解的是:这不应该慢,而是快得惊人。也完全不正确。要修复您的查询:
UPDATE counties c
SET the_geom_popcentroid = (
SELECT g.the_geom
FROM geonames g
WHERE ST_Contains(c.the_geom, g.the_geom)
ORDER BY g.population DESC
LIMIT 1
);
这会更新所有个县。如果一个县根本不应该包含任何地理名称,则the_geom_popcentroid
将设置为NULL。
这一具有 JOIN 语法的替代版本仅更新包含至少一个地理名称的县:
UPDATE counties c
SET the_geom_popcentroid = sub.the_geom
FROM (
SELECT DISTINCT ON (c1.pk)
c1.pk, g1.the_geom
FROM counties c1
JOIN geonames g1 ON ST_Contains(c1.the_geom, g1.the_geom)
ORDER BY c1.pk, g1.population DESC
) sub
WHERE c.pk = sub.pk;
其中 pk
是 counties
的主键列(或任何唯一列)。
DISTINCT ON
的说明:
不确定哪个更快。当尝试在两个 the_geom
列上使用索引时,ST_Contains()
与 ORDER BYthird_column LIMIT n
的组合可能会很棘手。如果重要的话,请使用EXPLAIN ANALYZE
进行测试。
有时,LATERAL JOIN
可以帮助说服 Postgres 使用索引。相关问题:
关于sql - 从多边形中包含的点集中指定人口最多的点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24999651/