PostgreSQL-用每一行的单独子查询更新多列

时间:2018-08-23 10:54:36

标签: sql postgresql postgis

我有多个这样的更新查询。我正在使用postgis和pg_trgm扩展来提供函数similarityST_Buffer以及&&运算符,但这并不重要,因为它们可以很容易地被其他条件替换。至关重要的是,我为每一行有一个单独的选择子查询,但没有为每个更新语句

UPDATE table0 AS t0 
SET value1 = value1 OR
(SELECT coalesce(BOOL_OR(t1.value1),FALSE)
 FROM table1 AS t1
 WHERE similarity(t1.name,t0.name)>0.7 AND t1.geom && ST_Buffer(t0.geom, 500, 3))
WHERE t0.need_update;

UPDATE table0 AS t0 
SET value2 = value2 OR
(SELECT coalesce(BOOL_OR(t1.value2),FALSE)
 FROM table1 AS t1
 WHERE similarity(t1.name,t0.name)>0.7 AND t1.geom && ST_Buffer(t0.geom, 500, 3))
WHERE t0.need_update;

...

现在,我想加快这些查询的速度。 table1table2都很安静(数百万行)。大部分查询时间可能都用于子查询,并且由于每个更新语句的查询时间都相同,因此我很确定我可以通过组合所有查询来实现。

但是如何?

我已经尝试过以下操作:

UPDATE table0 AS t0 
SET value1 = value1 OR t1val1, value2 = value2 OR t1val2
FROM
(SELECT coalesce(BOOL_OR(t1.value1),FALSE) AS t1val1, coalesce(BOOL_OR(t1.value2),FALSE) AS t1val2
 FROM table1 AS t1
 WHERE similarity(t1.name,t0.name)>0.7 AND t1.geom && ST_Buffer(t0.geom, 500, 3)) AS subquery
WHERE t0.need_update;

但这会导致:

ERROR:  invalid reference to FROM-clause entry for table "t0"
LINE 6:  WHERE similarity(t1.name,t0.name)>0.7 and t1.geom && ST...
                                  ^
HINT:  There is an entry for table "t0", but it cannot be referenced from this part of the query.

有什么想法吗?感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

getRandomColor(randomColor) {
    this.color = '#'; // <-----------
    for (var i = 0; i < 6; i++) {
        this.color += this.letters[Math.floor(Math.random() * 16)];
    }
}

是错误的语法;您不应重复使用SET value1 = value1 OR t1val1, SET value2 = value2 OR t1val2 关键字

SET

,我还将别名添加到了引用中。


此更新(通常)将布尔列从False更改为True:


    SET value1 = t0.value1 OR subquery.t1val1
      , value2 = t0.value2 OR subquery.t1val2
    ...

同样,直接使用UPDATE table0 AS t0 SET value1 = True WHERE t0.value1 = False -- Only change it if it is not already set AND t0.need_update AND EXISTS (SELECT * FROM table1 AS t1 WHERE similarity(t1.name,t0.name) > 0.7 -- I think you want st_dwithin() here; not sure AND t1.geom && ST_Buffer(t0.geom, 500, 3) ) ; 的布尔结果:


EXISTS()

顺便说一句:我认为,您还需要一个额外的条件来防止t0和t1引用相同的记录,例如:

UPDATE table0 AS t0 
SET value1 = EXISTS (SELECT *
        FROM table1 AS t1
        WHERE similarity(t1.name,t0.name) > 0.7
        AND t1.geom && ST_Buffer(t0.geom, 500, 3)
        )
WHERE t0.value1 = False -- Only change it if it is not already set
AND t0.need_update
 ;