【问题标题】:How to generate a new table in PostgreSQL by iterating over an existing table of OSM data如何通过迭代现有的 OSM 数据表在 PostgreSQL 中生成新表
【发布时间】:2026-01-18 10:25:01
【问题描述】:

我有一个由伦敦的 OSM 地图数据组成的 PostgreSQL 数据库。我使用 osm2psql 导入了这些数据。我想:

  • 遍历planet_osm_line 表中的每一行
  • 将线条分成单独的线段
  • 计算每条线段的值(在本例中将值设置为 0.5)
  • 将线段作为新条目写入新表中。

下面的 python 代码似乎实现了这一点,但有一个问题。它似乎只是访问整个数据库的一小部分。

import psycopg2

conn = psycopg2.connect("dbname=db user=username")
maincur = conn.cursor()
readcur = conn.cursor()
writecur = conn.cursor()

maincur.execute("DROP TABLE lines_red")
maincur.execute("CREATE TABLE lines_red (osm_id bigint, name text, way geometry, value float);")

maincur.execute("SELECT osm_id, ST_NPOINTS(way) FROM planet_osm_line")
    for record in maincur:
    pointlist = []
    for i in range(0,record[1]):
        readcur.execute("SELECT ST_ASTEXT(ST_POINTN(way, %s+1)) FROM planet_osm_line WHERE osm_id=%s;",(i,record[0]))
        output = readcur.fetchone()
        pointlist.append(output[0])
    for i in range(0,record[1]-1):  
        if pointlist[i+1] != None:
            value = 0.5
            writecur.execute("INSERT INTO lines_red (name, way, value) VALUES ('testname', ST_Makeline(%s, %s), %s);", (pointlist[i],pointlist[i+1],value))

conn.commit()
maincur.close()
readcur.close()
writecur.close()
conn.close()

为了说明,下图显示了完整的planet_osm_line 表,以灰色显示,查询结果以红色显示。红线应该覆盖整个地图,因为代码应该遍历整个planet_osm_line 表。我正在使用 tilemill 来显示结果。

【问题讨论】:

  • 顺便说一句:你真的必须迭代吗?在我看来,代码似乎可以用普通的旧 SQL 重写:insert into c(x,y,z) select p,q,l from a join b on a.p = b.k(甚至:create table c AS (select p,q,l from a join b ...)
  • 我想对新表中的每一行进行计算(基于起点和终点),SQL 不支持我需要的所有操作。我并不特别担心计算时间,我只是希望能够在 python 中进行计算。

标签: python postgresql psycopg2 openstreetmap tilemill


【解决方案1】:

在这种情况下,问题在于我使用 TileMill。

创建新图层时,其范围的默认设置是根据用作输入的数据库表进行预先计算。这意味着该层将永远是最初创建它的数据集的大小。

在这种情况下,我迭代了我的数据子集作为我的代码测试,并根据结果计算范围。当我遍历整个数据集时,代码会遍历整个数据库,但只显示先前计算的约束范围内的结果。

解决方法是新建一个图层或将图层中的extents设置为“动态”而不是“预先计算”

【讨论】:

    最近更新 更多