如何将SELECT嵌套到PL / pgSQL中的UPDATE语句中

时间:2018-07-07 19:22:18

标签: postgresql select sql-update plpgsql

我有下面的代码,效果很好,问题是我每次都创建一个表,这意味着我需要重新创建所有索引,并在创建新表时删除旧表。

DO
$do$
DECLARE
    m   text;
    arr text[] := array['e09000001','e09000007','e09000033','e09000019'];
BEGIN
    FOREACH m IN ARRAY arr
    LOOP
        EXECUTE format($fmt$
            CREATE TABLE %I AS
            SELECT a.ogc_fid,
                   a.poly_id,
                   a.title_no,
                   a.wkb_geometry,
                   a.distcode,                 
                   SUM(COALESCE((ST_Area(ST_Intersection(a.wkb_geometry, b.wkb_geometry))/ST_Area(a.wkb_geometry))*100, 0)) AS aw
            FROM %I a
                LEFT OUTER JOIN filter_ancientwoodlands b ON
                    ST_Overlaps(a.wkb_geometry, b.wkb_geometry) OR ST_Within(b.wkb_geometry, a.wkb_geometry)
            GROUP BY a.ogc_fid,
                     a.poly_id,
                     a.title_no,
                     a.wkb_geometry,
                     a.distcode;
        $fmt$, m || '_splitv2_aw', m || '_splitv2_distcode');
    END LOOP;
END
$do$

相反,我只想在现有表中创建一个新列并对其进行更新。我已经通过简单的查询来做到这一点,例如:

ALTER TABLE e09000001 ADD COLUMN area double precision;
UPDATE e09000001 SET area=ST_AREA(wkb_geometry);

我想弄清楚在上面更复杂的SELECT语句中使用UPDATE和SET时遇到了很多麻烦。有谁知道我怎么能做到这一点?

更新:所以我尝试了@abelisto的建议:

UPDATE test_table
SET aw = subquery.aw_temp
FROM (SELECT SUM(COALESCE((ST_Area(ST_Intersection(a.wkb_geometry, b.wkb_geometry))/ST_Area(a.wkb_geometry))*100, 0)) AS aw_temp
            FROM test_table a
                LEFT OUTER JOIN filter_ancientwoodlands b ON
                    ST_Overlaps(a.wkb_geometry, b.wkb_geometry) OR ST_Within(b.wkb_geometry, a.wkb_geometry)
            GROUP BY a.ogc_fid,
                     a.poly_id,
                     a.title_no,
                     a.wkb_geometry,
                     a.distcode) AS subquery;

但是查询只需要花费几秒钟的时间就运行了很长时间(一个小时)。谁能看到我的代码中的错误?

1 个答案:

答案 0 :(得分:2)

您需要一个WHERE子句才能将from表达式连接到update表。

也许是这样。

UPDATE test_table
SET aw = subquery.aw_temp
FROM (SELECT SUM(COALESCE((ST_Area(ST_Intersection(a.wkb_geometry, b.wkb_geometry))/ST_Area(a.wkb_geometry))*100, 0)) AS aw_temp,a.wkb_geometry
            FROM test_table a
                LEFT OUTER JOIN filter_ancientwoodlands b ON
                    ST_Overlaps(a.wkb_geometry, b.wkb_geometry) OR ST_Within(b.wkb_geometry, a.wkb_geometry)
            GROUP BY a.ogc_fid,
                     a.poly_id,
                     a.title_no,
                     a.wkb_geometry,
                     a.distcode) AS subquery
WHERE
    subquery.wkb_geometry = test_table.wkb_geometry;