sqlite 如何在Spatialite中分解几何,例如将每个MultiLineString要素转换为多个LineString要素

7y4bm7vi  于 12个月前  发布在  SQLite
关注(0)|答案(1)|浏览(203)

我使用带有Spatialite扩展名的sqlite来查询一个数据包文件。
考虑以下测试表,其中每行的几何类型为LineString或MultiLineString。

sqlite>load_extension('mod_spatialite');
sqlite>select EnableGpkgMode(); -- I'm testing on GeoPackage
sqlite>SELECT id,geom FROM mix AS ft;
1|LINESTRING(10 0,10 60)
2|MULTILINESTRING( (40 0,40 60), (50 0,50 60) )

字符串
我需要一个结果,其中每个MultiLineString被“分解”成许多LineString,如下所示:

1|1|LINESTRING(10 0,10 60)
2|2.1|LINESTRING( 40 0,40 60 )
2|2.2|LINESTRING( 50 0,50 60 )


如果可能的话,我希望两者都保留原来的id,并创建一个新的newid,如上所示。
下面的解决方案在PostGIS中工作,但我仍然没有找到Spatialite的解决方案。

postgis=> SELECT
    id,
    array_to_string(
        id || (ST_Dump(geom)).path,
        '.'
    ) AS newid,
    ST_AsText((ST_Dump(geom)).geom) AS geom
FROM cubetown.MixLS_1
;
 id | newid |          geom          
----+-------+------------------------
  1 | 1     | LINESTRING(10 0,10 60)
  2 | 2.1   | LINESTRING(40 0,40 60)
  2 | 2.2   | LINESTRING(50 0,50 60)

9cbw7uwe

9cbw7uwe1#

SQLite本质上不支持ST_Dump等集合返回函数。您需要使用一种解决方法,通常是通过递归CTE。下面的SQLite/Spatialite SQL语句应该可以做到这一点:

WITH RECURSIVE mix (id, geom) AS (VALUES
  (1, ST_GeomFromText('LINESTRING(10 0,10 60)')),
  (2, ST_GeomFromText('MULTILINESTRING( (40 0,40 60), (50 0,50 60) )'))
), n_max AS (
  SELECT max(ST_NumGeometries(geom)) as m
  FROM mix
), nlist AS (
  SELECT 1 AS n
UNION ALL
  SELECT n + 1
  FROM nlist, n_max
  WHERE n < m
)
SELECT id, n, 
  CASE
    WHEN ST_NumGeometries(geom) = 1 THEN 1
    ELSE id || '.' || n
  END AS newid,
  ST_GeometryN(geom, n) AS geom
FROM mix, nlist
WHERE ST_GeometryN(geom, n) IS NOT NULL;

字符串
简短说明:

  • 关键字RECURSIVE必须直接放在WITH之后,即使实际的递归CTE“nlist”很晚才跟在后面
  • CTE“n_max”获取存储在列“m”中的任何(多)Linestring中的Linestring的最大数量
  • 递归CTE“nlist”在顺序记录中生成一个数字从1到n_max.m的记录集(它在功能上等同于集合返回函数)
  • 最后的主SELECT使用ST_GeometryN通过使用表“mix”和“nlist”之间的交叉连接,从MultiLinestring中提取第n个linestring
  • 在许多情况下,原始几何体中的实际LineStrings比请求的第n个几何体少,导致NULL几何体。这些都被排除在最终结果集之外。

相关问题