有没有办法在单个空间查询上设置多个列值?

Is there a way to set multiple column values on a single spatial query?

我正在使用 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创建一个新的临时文件table,在一个点的 2 以内为每行记录,然后设置值关闭 table 会更有效吗]?描述它,它听起来效率较低,因为 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 以来可能。然而,也有相当大的缺点。

该表单无条件地 table 更新每一行。您将不得不在 WHERE 子句中重复计算以有条件地进行计算,这违背了只进行一次的目的。

在 PostgreSQL 的 MVCC 模型中 UPDATE 基本上意味着编写完整行的新版本,膨胀 table 和索引。本身很昂贵,但如果您不能或不清理,还会导致 VACUUM - and/or 性能下降的大量额外工作。参见:

要么你真的想更新每一行,那基本上没问题。但是,如果您不受并发负载或对 table(视图、FK、...)的内部引用的约束,请考虑编写一个新的 table。通常总体上更便宜。

但是,某些(或 many/most?)行可能已经是最新的。那是巨大的浪费。请考虑:

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)

这不会涉及实际未更改的行。

我们需要 FROM 子句中的 scratch.intersections 的附加实例以允许 LATERAL 加入。但是我们在应用更新之前删除了所有没有更改的行 - 这样可以为已经更新的每一行节省大部分工作。好吧,由于子查询相对昂贵,也许不是 most 的工作。但通常情况下,实际的写入操作比计算新值要昂贵得多。

这与您在上一段中的想法非常接近。但是在不创建临时文件的情况下效率更高 table,并且您还可以保存空写入。

如果您只需要在 streets.geom 中更改几行后更新 intersections 中可能受影响的行,那么还有更多优化潜力。不去,好像超出了这个问题的范围。

相关:

  • How do I (or can I) SELECT DISTINCT on multiple columns?