我有一条有效的SELECT语句,但由于SQL不是我的强项,我不知道如何将其变成UPDATE函数.我还有其他人在工作,但似乎是Join让我来到了这里.

我试了几种我能想到的方法: UPDATE PTP_LINKS SET GEOM=ST_MAKELINE(这会使每个记录获得相同的行) UPDATE FOR SELECT(这个命令获得了闭合,但抛出了一个关于列"geom"的类型是GEOMETRY,但表达式是RECORD类型的错误)

这是我的SELECT查询:

SELECT 
  ST_MAKELINE(
    ST_POINT(out_bs.longitude::DOUBLE PRECISION, out_bs.latitude::DOUBLE PRECISION, 4326),
    ST_POINT(CASE WHEN ptp.link_purpose = 'backhaul'
      THEN in_bs.longitude::DOUBLE PRECISION
      ELSE ptp.in_address_geo_x::DOUBLE PRECISION
    END,
    CASE WHEN ptp.link_purpose = 'backhaul'
      THEN in_bs.latitude::DOUBLE PRECISION
      ELSE ptp.in_address_geo_y::DOUBLE PRECISION
    END, 4326)
  )
FROM ptp_links ptp
LEFT JOIN base_stations in_bs ON ptp.in_base_station = in_bs.id
LEFT JOIN base_stations out_bs ON ptp.out_base_Station = out_bs.id;

我想要做的是将从ST_MAKELINE生成的行写回到PTP_LINKS表中名为geom的列中,如果有人知道我将如何在PostGIS中这样做的话.

推荐答案

你可以在标准的update..from..where号中依靠implicit joins号:

当存在FROM子句时,实质上发生的是目标表连接到101列表中提到的表,并且连接的每个输出行表示对目标表的更新操作.

Demo:

UPDATE ptp_links AS ptp
SET geom = ST_MAKELINE(
                ST_POINT(out_bs.longitude::DOUBLE PRECISION,
                         out_bs.latitude::DOUBLE PRECISION, 
                         4326),
                ST_POINT(CASE WHEN ptp.link_purpose = 'backhaul'
                              THEN in_bs.longitude::DOUBLE PRECISION
                              ELSE ptp.in_address_geo_x::DOUBLE PRECISION END,
                         CASE WHEN ptp.link_purpose = 'backhaul'
                              THEN in_bs.latitude::DOUBLE PRECISION
                              ELSE ptp.in_address_geo_y::DOUBLE PRECISION END, 
                         4326)
            )
FROM base_stations in_bs,
     base_stations out_bs
WHERE ptp.in_base_station  = in_bs.id
AND   ptp.out_base_Station = out_bs.id
RETURNING ptp.id,in_base_station,out_base_station,link_purpose,st_astext(geom);
id in_base_station out_base_station link_purpose st_astext
1 1 2 backhaul LINESTRING(2 1,0 0)
2 2 3 backhaul LINESTRING(3 2,2 1)
3 3 4 other LINESTRING(4 3,17 23)

如果您还从ptp_links中获取一些唯一标识符,则可以将select包装在with CTE中,并将其用作update语句的源:demo

WITH update_batch AS (
    SELECT ptp.id,--something unique to targeted record
      ST_MAKELINE(
        ST_POINT(out_bs.longitude::DOUBLE PRECISION,
                 out_bs.latitude::DOUBLE PRECISION, 
                 4326),
        ST_POINT(CASE WHEN ptp.link_purpose = 'backhaul'
          THEN in_bs.longitude::DOUBLE PRECISION
          ELSE ptp.in_address_geo_x::DOUBLE PRECISION
        END,
        CASE WHEN ptp.link_purpose = 'backhaul'
          THEN in_bs.latitude::DOUBLE PRECISION
          ELSE ptp.in_address_geo_y::DOUBLE PRECISION
        END, 4326)
      ) AS new_geom
    FROM ptp_links ptp
    LEFT JOIN base_stations in_bs ON ptp.in_base_station = in_bs.id
    LEFT JOIN base_stations out_bs ON ptp.out_base_Station = out_bs.id )
UPDATE ptp_links AS t
SET geom = new_geom
FROM update_batch AS s
WHERE s.id = t.id
RETURNING t.id,in_base_station,out_base_station,link_purpose,st_astext(geom);

包装基本查询的另一种方法是将其直接馈送到update...set geom=赋值:demo

UPDATE ptp_links AS target
SET geom = (SELECT ST_MAKELINE(
                ST_POINT(out_bs.longitude::DOUBLE PRECISION,
                         out_bs.latitude::DOUBLE PRECISION, 
                         4326),
                ST_POINT(CASE WHEN ptp.link_purpose = 'backhaul'
                  THEN in_bs.longitude::DOUBLE PRECISION
                  ELSE ptp.in_address_geo_x::DOUBLE PRECISION
                END,
                CASE WHEN ptp.link_purpose = 'backhaul'
                  THEN in_bs.latitude::DOUBLE PRECISION
                  ELSE ptp.in_address_geo_y::DOUBLE PRECISION
                END, 4326)
              ) AS new_geom
            FROM ptp_links ptp
            LEFT JOIN base_stations in_bs ON ptp.in_base_station = in_bs.id
            LEFT JOIN base_stations out_bs ON ptp.out_base_Station = out_bs.id 
            WHERE ptp.id=target.id
            LIMIT 1 );

请注意,在后两种情况下,您需要通过比较唯一标识符将传入的值定向到目标行.就像reminded乘以@Bergi一样,如果你没有,总会有"hidden" ctid column可用.请记住,ctid在单个查询中是稳定的,但不能保证在单独的、甚至是连续的查询之间保持一致.

Postgresql相关问答推荐

如何使用postgr sql regex删除重复项和inc表记录

在PostGreSQL中获取最近日期的项目

Postgres 对 WHERE 子句并行使用两个索引

JPA将没有时区的Postgres时间戳调整为服务器时区

在 PostgreSQL 中 Select 数字命名列会返回 ?column?

如何将 NULL 值插入 UUID 而不是零

使用间隔参数的 go postgres 准备好的语句不起作用

PostgreSQL 查询到 Excel 表

MAC OS X 上的 Postgres 权限被拒绝

错误:must be owner of language plpgsql

用于更改 postgresql 用户密码的 bash 脚本

如何从另一个脚本运行 postgres sql 脚本?

你如何在postgresql中做mysqldump?

如何增加 max_locks_per_transaction

PGError:错误: column of relation does not exist

如何将表的一列复制到PostgreSQL中比较相同ID的另一表的列

在 Windows 7 上更改/重置 postgresql 用户密码

如何使用 PostgreSQL 在任何列中查找所有具有 NULL 值的行

postgresql DB中唯一键的正确数据类型是什么?

提高查询速度:simple SELECT in big postgres table