【问题标题】:Insert forms from a query in postgis从 postgis 中的查询中插入表单
【发布时间】:2016-08-29 08:09:53
【问题描述】:

我尝试通过查询在我的表geofield 中插入一个多边形。表geofield 定义如下:

CREATE TABLE geofield(id SERIAL PRIMARY KEY, field GEOMETRY);

insert into geofield(field) values (myfield)
SELECT
    'POLYGON(('||cast((select lat from coordinates where id=1)as varchar)||' '||
      cast((select lon from coordinates where id=1)as varchar)||','||
      cast((select lat from coordinates where id=2)as varchar)||' '||
      cast((select lon from coordinates where id=2)as varchar)||','||
      cast((select lat from coordinates where id=3)as varchar)||' '||
      cast((select lon from coordinates where id=3)as varchar)||','||
      cast((select lat from coordinates where id=4)as varchar)||' '||
      cast((select lon from coordinates where id=4)as varchar)||','||
      cast((select lat from coordinates where id=1)as varchar)||' '||
      cast((select lon from coordinates where id=1)as varchar)||'))') AS myfield;

SELECT 单独返回我:

POLYGON((46.744628268759314 6.569952920654968,46.74441692818192 6.570487107359068,46.74426116111054 6.570355867853787,46.74447250168793 6.569821681149689,46.744628268759314 6.569952920654968))

但它不起作用,我也尝试了 ST_GeomFromText 但结果相同。

【问题讨论】:

  • INSERT INTO ... SELECT 的适当语法不包括VALUES 部分。所以:INSERT INTO geofield (field) SELECT whatever.
  • 另外,指定您遇到的实际错误或行为绝对是一项要求。 “它不起作用”只是没用的。
  • 非常感谢!是价值观锁定了我,我花了很多时间试图弄清楚:/

标签: postgresql postgis


【解决方案1】:

我会避免使用文本连接,而是使用普通的PostGIS functions

SELECT
    /* Make a polygon from the linestring */
    ST_MakePolygon(
        /* Close the polygon */
        ST_AddPoint(
            t.linestring,
            ST_StartPoint(t.linestring)
        )
    )
FROM (
    SELECT
        /* Aggregate into a linestring */
        ST_MakeLine(ST_MakePoint(c.lon, c.lat) ORDER BY c.id) AS linestring
    FROM coordinates AS c
) t
;

按照您的prior question,如果您愿意,可以直接从json 取回:

SELECT
    /* Make a polygon from the linestring */
    ST_MakePolygon(
        /* Close the polygon */
        ST_AddPoint(
            t.linestring,
            ST_StartPoint(t.linestring)
        )
    )
FROM (
    SELECT
        /* Aggregate into a linestring */
        ST_MakeLine(ST_MakePoint(c.lon, c.lat) ORDER BY c.id) AS linestring
    FROM
    (
        SELECT
            e.id,
            (e.element->>'lat')::numeric AS lat,
            (e.element->>'lon')::numeric AS lon
        FROM
            field AS f,
            json_array_elements(f.data->'vertices') WITH ORDINALITY AS e(element, id)
    ) AS c
) t
;

【讨论】:

  • 谢谢!最后,我使用您的最后一个解决方案。这是更有效的一个:) 现在我处理另一个 json 文件,其中包含要放置在多边形中的点,感谢您的帮助,我想我可以自己管理它。
  • @gabrielchauviere:不客气。而且,好吧,您可以将答案标记为已接受(在两个问题中)... ;)
【解决方案2】:

字符串是正确的 WKT 格式,所以这不是问题。问题是您的经度和纬度值颠倒了,INSERT 的语法是错误的。您还应该先将字符串转换为geometry

INSERT INTO geofield(field)
    SELECT ST_GeomFromText(
        'POLYGON(('||cast((select lat from coordinates where id=1)as varchar)||' '||
          cast((select lon from coordinates where id=1)as varchar)||','||
          cast((select lat from coordinates where id=2)as varchar)||' '||
          cast((select lon from coordinates where id=2)as varchar)||','||
          cast((select lat from coordinates where id=3)as varchar)||' '||
          cast((select lon from coordinates where id=3)as varchar)||','||
          cast((select lat from coordinates where id=4)as varchar)||' '||
          cast((select lon from coordinates where id=4)as varchar)||','||
          cast((select lat from coordinates where id=1)as varchar)||' '||
          cast((select lon from coordinates where id=1)as varchar)||'))');

但这一切都非常浪费,不适合较大的多边形。只要你的多边形由一个环组成,你就可以这样做,这样会更快,更不容易出错:

INSERT INTO geofield(field)
    SELECT ST_GeomFromText('POLYGON((' || coords.c || ',' || coord1.c || '))', 4326)
    FROM
        ( SELECT string_agg(lon::text || ' ' || lat::text, ',' ORDER BY id) AS c
          FROM coordinates ) coords,
        ( SELECT lon::text || ' ' || lat::text AS c
          FROM coordinates
          WHERE id = 1 ) coord1;

第一个子查询将所有坐标串在一起,而第二个子查询只获取第一个坐标以关闭多边形。使用尽可能多的点。

【讨论】:

  • 谢谢,我永远不会考虑这个(我不是 SQL 专家),它工作得很好!
  • 唯一的错误是返回错误的 ORDER BY:列“coordinates.id”必须出现在 GROUP BY 子句中或在聚合函数中使用。我删除了它,它可以工作
  • 首先,你使用ORDER BY的方式也不能保证顺序,你应该有ORDER BY inside string_agg函数调用而不是在查询中使用它(实际上对查询没用)。其次,您正在聚合并获得未聚合的“id”,但您没有使用GROUP BY(第一个修复也应该解决这个问题,只需将ORDER BY 从查询移动到聚合函数调用,就像我在我的答案)
  • @MatheusOl 完全正确,感谢您指出这一点。答案已更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
  • 2016-08-26
  • 2014-05-05
  • 1970-01-01
  • 2016-03-15
相关资源
最近更新 更多