我正在使用PostGIS的属性与点关联。ST_DWIthin()
.
UPDATE scratch.intersections AS i
SET legs = (
SELECT COUNT(r.geom)
FROM received.streets r
WHERE ST_DWithin(i.geom, r.geom, 2));
UPDATE scratch.intersections AS i
SET streets = (
SELECT ARRAY_AGG(DISTINCT r.NAME ORDER BY r.NAME)
filter (WHERE r.NAME IS NOT NULL)
FROM received.streets r
WHERE ST_DWithin(i.geom, r.geom, 2));
似乎应该可以用一个空间查询更新多列,但我想不出一种结构化的方法,因为我每次只能更新一列。
有没有办法把这两个查询变成一个查询,只需要一个空间计算?
如果做一个 INNER JOIN
创建一个新的临时表,在某点的2以内的每条线都有一条记录,然后在该表上设置数值?描述,这听起来效率较低,因为性能的 ST_DWithin()
使用索引并不可怕。
可以在一个语句中用括号括起多个列来更新它们
UPDATE myTable
SET (a,b) = (
select c,d
from anotherTable
WHERE st_dwithin(mytable.geom, anotherTable.geom,2)
);
JGH提供了一个聪明的方法来 UPDATE
从一个(相关的)子查询中同时查询多个列。从Postgres 9.5开始可以实现。然而,有相当大的缺点。
该表单更新了表中的每一行 无条件. 你必须重复计算在 WHERE
子句来有条件地做,这将违背只做一次的目的。
在PostgreSQL的MVCC模型中 UPDATE
基本上意味着要写一个新版本的完整行,臃肿的表和索引。本身就很贵,但也造成了很多额外的工作,对 VACUUM
- 和或性能下降,如果你不能或不清理。请看
要么你真的想更新每一行,那么基本就可以了。虽然,如果你不受并发负载或表的内部引用(视图、FK......)的约束,可以考虑写一个新表代替。通常整体上比较便宜。
但是,有些(或者说大部分?)行可能已经是最新的了。那么这就是一个 巨大的浪费. 而是考虑。
UPDATE scratch.intersections AS i
SET legs = r.legs
, streets = r.streets
FROM scratch.intersections x
JOIN LATERAL (
SELECT count(*) AS legs -- assuming r.geom is NOT NULL
, array_agg(DISTINCT s.NAME ORDER BY s.NAME)
FILTER (WHERE s.NAME IS NOT NULL) AS streets
FROM received.streets s
WHERE ST_DWithin(x.geom, s.geom, 2)
) r ON x.legs IS DISTINCT FROM r.legs
OR x.streets IS DISTINCT FROM r.streets
WHERE i.id = x.id; -- id being the PK (or at least UNIQUE)
这不会触及那些没有实际变化的行。
我们需要额外的 scratch.intersections
在 FROM
条款,以允许 LATERAL
连接。但是我们在应用更新之前,先消除所有没有变化的行--这样就为每一条已经更新的行节省了大部分工作。好吧,由于子查询的成本比较高,也许不需要了 最 的工作。但通常情况下,实际的写操作比计算新的值要贵得多。
这和你最后一段的想法很接近。但是不用创建临时表,效率更高,而且还可以节省空写。
而且如果你只需要更新可能受影响的行,在 intersections
换了几行 streets.geom
,还有更多的优化潜力,还。不去,似乎不在这个问题的范围内。
相关的。