将数据从GeoJSON转换为SQL地理

时间:2017-05-08 20:08:24

标签: sql sql-server json sql-server-2016 geo

基础知识首先,服务器是MS SQL Server 2016开发人员版,我正在将存储在NvarChar(max)列中的县形状数据作为GeoJson转换为sql地理字段,以便更好地进行存储和空间索引。现在数据存储为blob,我正在尝试优化存储并创建空间索引以加快位置比较(EG:X公路是否与Y县相交)。

有很多关于从sql地理数据到Geo-JSON的文档,但没有那么多关于反向的文档。我已经完成了它的工作,但我想到必须有一种更简单的方法来进行这种转换。以下是我到目前为止的情况:

declare @Silly varchar(max) =  (select CountyJSON from [dbo].[Counties] where name = 'Piute')

declare @GeoString nvarchar(max) = 
(select 
   '''' + upper(ShapeType) + '((' + 
       replace(
           replace(
                   RePlace(
                      replace(Shape, '[', '')
                   , ',', ' ')
               , ']]]', ''),
        ']', ',')
    + '))' + ''''
from  
   openjson(@Silly)
with (ShapeType Varchar(64) '$.type',
      Shape nvarchar(max) '$.coordinates' as json)
)

declare @String nvarchar(max) = ( select 'select geography::STGeomFromText(' + @GeoString + ', 4326) as geodata')

exec (@String)

我必须使用Replace(多次)来正确格式化JSON数据,因为SQL可以使用,这使得查询的一部分变得混乱,但基本上我已经摆脱了[和]]],添加了一个空格在坐标中间而不是逗号,并将其更改为逗号。我将不得不为多种多样的县提出一些更精细的东西。然后我不得不使用动态sql来获取stgeomfromtext到函数。这似乎是一个非常糟糕的方法,有没有人知道更好的方法?

我只会下载县的地理位置值,但我被告知保留现有数据,所以这是一个奇怪的请求,会变成很多工作。

这是犹他州皮特县的Geo-json(选择因为它小而简单):

{"type":"Polygon","coordinates":[[[-111.766741,38.501977],[-111.823854,38.457266],[-111.836911,38.428477],[-111.848871,38.425001],[-111.8428,38.15128],[-111.951449,38.151083],[-111.951349,38.145983],[-112.021169,38.145776],[-112.060929,38.14928],[-112.443821,38.149942],[-112.422573,38.170683],[-112.424117,38.181411],[-112.357074,38.224502],[-112.381019,38.249974],[-112.352591,38.279368],[-112.335369,38.332955],[-112.343404,38.347312],[-112.361492,38.355579],[-112.380363,38.379892],[-112.403869,38.394836],[-112.402939,38.415581],[-112.417117,38.419483],[-112.436247,38.402077],[-112.452491,38.428824],[-112.512674,38.468696],[-112.510259,38.488097],[-112.518504,38.509852],[-112.257811,38.512044],[-112.062533,38.510513],[-112.062501,38.50195],[-111.766741,38.501977]]]}

提前感谢你们给我的任何帮助。

2 个答案:

答案 0 :(得分:2)

也许是这样的:

declare @Silly nvarchar(max) = '{"type":"Polygon","coordinates":[[[-111.766741,38.501977],[-111.823854,38.457266],[-111.836911,38.428477],[-111.848871,38.425001],[-111.8428,38.15128],[-111.951449,38.151083],[-111.951349,38.145983],[-112.021169,38.145776],[-112.060929,38.14928],[-112.443821,38.149942],[-112.422573,38.170683],[-112.424117,38.181411],[-112.357074,38.224502],[-112.381019,38.249974],[-112.352591,38.279368],[-112.335369,38.332955],[-112.343404,38.347312],[-112.361492,38.355579],[-112.380363,38.379892],[-112.403869,38.394836],[-112.402939,38.415581],[-112.417117,38.419483],[-112.436247,38.402077],[-112.452491,38.428824],[-112.512674,38.468696],[-112.510259,38.488097],[-112.518504,38.509852],[-112.257811,38.512044],[-112.062533,38.510513],[-112.062501,38.50195],[-111.766741,38.501977]]]}';

with q as
(

select 1 ShapeId, ShapeType, 
   stuff( 
      (
        select concat(',  ', json_value(Value,'$[0]'),' ',json_value(Value,'$[1]'))  
        from openjson(s.Shape,'$[0]') 
        order by cast([key] as int)
        for xml path('')
      ),1,3,'') path
from  
   openjson(@Silly) 
   with (ShapeType Varchar(64) '$.type',
         Shape nvarchar(max) '$.coordinates' as json) s
), q2 as
(
  select ShapeId, concat(upper(ShapeType),'((',path,'))') WKT
  from q
)
select ShapeId, geography::STGeomFromText(WKT,4326) as geodata from q2

答案 1 :(得分:0)

您是否尝试过从here偷来的以下内容?

declare @polygon nvarchar(max) =
N'{ "type": "Polygon",
    "coordinates": [
        [[30, 10], [40, 40], [20, 40], [10, 20], [30, 10]]
    ]
}'

SELECT x, y
FROM OPENJSON(@polygon, '$.coordinates[0]')
          WITH (x int '$[0]', y int '$[1]')

编辑:我明白了,这不是你想要的。您是否考虑过将geoJSON数据转换为WKB并使用以下内容?

STPolyFromWKB ( 'WKB_polygon' , SRID )