Динамический массив Polygon JSON в столбец вычисляемой геометрии в SQL Server

#sql #json #sql-server #arcgis

#sql #json #sql-сервер #arcgis

Вопрос:

У меня есть столбец SQL Server, который содержит массив JSON (последовательность координат точек), которые составляют форму многоугольника. Это правильно отформатированный JSON, который представляет собой массив точек. Я хочу преобразовать этот массив JSON в столбец вычисляемой геометрии. Приведенный ниже пример представляет собой ОДНУ запись, но мне нужно, чтобы столбец был вычислен, поскольку я получаю эти данные в реальном времени в базу данных.

 [
    {"X":-135.4993896484375,"Y":40.8944206237793},
    {"X":-135.49931335449219,"Y":40.89435958862305},
    {"X":-135.4993667602539,"Y":40.89413070678711},
    {"X":-135.49922180175781,"Y":40.8939094543457},
    {"X":-135.49891662597656,"Y":40.89371109008789},
    {"X":-135.49922180175781,"Y":40.89352035522461},
    {"X":-135.49994659423828,"Y":40.89336013793945},
    {"X":-135.5006332397461,"Y":40.893218994140625},
    {"X":-135.50110626220703,"Y":40.892738342285156},
    {"X":-135.4993896484375,"Y":40.8944206237793}
]
 

Мой новый столбец может называться Shape или что-нибудь еще. Как мне проанализировать это и объединить его с STPolyFromText, чтобы перенести это в новый вычисляемый столбец?

Ответ №1:

 create or alter function dbo.jsonpolygon(@j nvarchar(max))
returns geometry
as
begin
    declare @geom geometry;
    
    select 
        @geom = 'POLYGON((' string_agg(concat(v.X, ' ', v.Y), ',') within group (order by j.[key]) '))'
    from openjson(case when isjson(@j) = 1 then @j end) as j
    cross apply openjson(case when isjson(j.value) = 1 then j.value end)
    with
    (
        X varchar(100),
        Y varchar(100)
    ) as v;
    
    return(@geom);
end
go


create table xyz -- table
(
json nvarchar(max),
geom as dbo.jsonpolygon(json)
)
go

insert into xyz(json)
values(
'[
    {"X":-135.4993896484375,"Y":40.8944206237793},
    {"X":-135.49931335449219,"Y":40.89435958862305},
    {"X":-135.4993667602539,"Y":40.89413070678711},
    {"X":-135.49922180175781,"Y":40.8939094543457},
    {"X":-135.49891662597656,"Y":40.89371109008789},
    {"X":-135.49922180175781,"Y":40.89352035522461},
    {"X":-135.49994659423828,"Y":40.89336013793945},
    {"X":-135.5006332397461,"Y":40.893218994140625},
    {"X":-135.50110626220703,"Y":40.892738342285156},
    {"X":-135.4993896484375,"Y":40.8944206237793}
]'
), ('12345'), ('[12345]');

/* this will break the calculated column
insert into t(json)
values(
'[
    {"X":-135.4993896484375,"Y":40.8944206237793}
]'
)
*/

select *
from xyz;
go

drop table xyz
go
drop function dbo.jsonpolygon
go
 

Комментарии:

1. Спасибо! Будет ли это работать с использованием столбца? Я использовал значения XY в качестве примера для одной ячейки, но на самом деле у меня тысячи записей, и мне нужна возможность просто ввести имя столбца.

2. ..@zanzibarjack . да, это будет работать для таблицы, вы можете добавить столбец вычисляемой геометрии. Если вы уверены, что все строки json вернут допустимый полигон, то все, что вам нужно сделать, это: alter table tableX add geomY as dbo.jsonpolygon(jsoncolumnZ) , просто замените TableX и geomYamp; jsoncolumnY соответствующими именами (нужное вам имя таблицы и вычисляемого столбца, имя столбца, в котором хранятся данные json). Можно сделать функцию менее подверженной ошибкам: для полигона требуется не менее 4 точек, а начальная точка == конечная точка, и вы могли бы включить это в функцию dbo.jsonpolygon() .