将数据从 GeoJSON 转换为 SQL 地理
Transforming Data from GeoJSON to SQL Geography
首先是基础知识,服务器是 MS SQL Server 2016 开发人员版,我正在将存储在 NvarChar(max) 列中的县形状数据作为 GeoJson 转换为 sql 地理字段以获得更好的存储和空间索引。现在数据存储为 blob,我正在尝试优化存储并创建空间索引以加速位置比较(例如:Does X highway intersect with Y county)。
有很多关于从 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 可以使用的内容,这使得查询的那部分变得混乱,但基本上我正在摆脱[和]]],在坐标中间加一个space代替逗号,把]改成逗号。我将不得不为多边形的县想出更详细的东西。然后我不得不使用动态 sql 来让 stgeomfromtext 发挥作用。这似乎是一个非常糟糕的方法,有没有人知道更好的方法?
我只想下载县的地理值,但我被告知要保留现有数据,所以这是一个奇怪的请求,会变成大量工作。
这是犹他州 Piute 县的 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]]]}
在此先感谢你们能给我的任何帮助。
你试过从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 )
也许是这样的:
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
首先是基础知识,服务器是 MS SQL Server 2016 开发人员版,我正在将存储在 NvarChar(max) 列中的县形状数据作为 GeoJson 转换为 sql 地理字段以获得更好的存储和空间索引。现在数据存储为 blob,我正在尝试优化存储并创建空间索引以加速位置比较(例如:Does X highway intersect with Y county)。
有很多关于从 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 可以使用的内容,这使得查询的那部分变得混乱,但基本上我正在摆脱[和]]],在坐标中间加一个space代替逗号,把]改成逗号。我将不得不为多边形的县想出更详细的东西。然后我不得不使用动态 sql 来让 stgeomfromtext 发挥作用。这似乎是一个非常糟糕的方法,有没有人知道更好的方法?
我只想下载县的地理值,但我被告知要保留现有数据,所以这是一个奇怪的请求,会变成大量工作。
这是犹他州 Piute 县的 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]]]}
在此先感谢你们能给我的任何帮助。
你试过从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 )
也许是这样的:
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