Разбор массива JSON в T-SQL

В нашей таблице SQL Server у нас есть объект json, хранящийся с массивом строк. Я хочу программно разбить эту строку на несколько столбцов. Однако я не могу заставить его работать, или даже если это возможно.

Это возможность создать несколько столбцов в предложении WITH или это более разумный шаг, чтобы сделать это в операторе select?

Я урезал часть кода, чтобы дать упрощенное представление о том, что дано.

Пример JSON похож на { "arr": ["str1 - str2"] }

SELECT b.* FROM [table] a
OUTER APPLY
OPENJSON(a.value, '$.arr')
WITH
(
    strSplit1 VARCHAR(100) SPLIT('$.arr', '-',1),
    strSplit2 VARCHAR(100) SPLIT('$.arr', '-',2)
) b

NB: { "arr": ["str1 - str2"] } - это массив, содержащий одну строку. { "arr": ["str1","str2"] } - это массив с двумя строками. Вы имели в виду последнее или первое верно?

JohnLBevan 24.10.2018 17:27

В SQL Server нет SPLIT. В SQL Server 2016+ есть STRING_SPLIT. Однако вам, вероятно, следует исправить содержимое JSON. Если вам нужен массив строк, зачем использовать ["str1 - str2"] вместо ["str1","str2"]?

Panagiotis Kanavos 24.10.2018 17:46
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
5
2
8 155
2

Ответы 2

Из-за тега [tsql] и использования OPENJSON я предполагаю, что это SQL-Server. Но может ошибаться ... Всегда указывайте вашу СУБД (с версией).

Ваш JSON довольно странный ... Я думаю, вы перестарались, пытаясь упростить это для краткости ...

Попробуй это:

DECLARE @tbl TABLE(ID INT IDENTITY,YourJSON NVARCHAR(MAX));
INSERT INTO @tbl VALUES(N'{ "arr": ["str1 - str2"] }') --weird example...
                      ,(N'{ "arr": ["a","b","c"] }');  --array with three elements

SELECT t.ID
      ,B.[value] AS arr
FROM @tbl t
CROSS APPLY OPENJSON(YourJSON) 
WITH(arr NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.arr) B;

Довольно короткий подход (но подходящий только для этого простого примера) заключался в следующем:

SELECT t.ID
      ,A.*
FROM @tbl t
OUTER APPLY OPENJSON(JSON_QUERY(YourJSON,'$.arr')) A 

Намекать

Поддержка JSON появилась в SQL-Server 2016.

ОБНОВЛЕНИЕ: если содержимое JSON представляет собой странную CSV-строку ...

Есть трюк для преобразования CSV в массив JSON. Попробуй это

DECLARE @tbl TABLE(ID INT IDENTITY,YourJSON NVARCHAR(MAX));
INSERT INTO @tbl VALUES(N'{ "arr": ["str1 - str2"] }') --weird example...
                      ,(N'{ "arr": ["a","b","c"] }')  --array with three elements
                      ,(N'{ "arr": ["x-y-z"] }');     --array with three elements in a weird CSV format

SELECT t.ID
      ,B.[value] AS arr
      ,C.[value]
FROM @tbl t
CROSS APPLY OPENJSON(YourJSON) 
WITH(arr NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.arr) B
CROSS APPLY OPENJSON('["' + REPLACE(B.[value],'-','","') + '"]') C;

Некоторые простые замены в OPENJSON('["' + REPLACE(B.[value],'-','","') + '"]') создадут массив JSON из вашей CSV-строки, который можно открыть в OPENJSON.

Я не знаю, как разделить строку в JSON. Интересно, связана ли проблема с вашим JSON, содержащим одну строку, а не несколько значений?

В приведенном ниже примере показано, как извлечь каждую строку из массива; и если вы хотите пойти дальше и разделить эти строки по дефису, покажет, как это сделать, используя обычные функции SQL SUBSTRING и CHARINDEX.

create table [table]
(
    value nvarchar(max)
)

insert [table](value)
values ('{ "arr": ["str1 - str2"] }'), ('{ "arr": ["1234 - 5678","abc - def"] }')

SELECT b.value
, rtrim(substring(b.value,1,charindex('-',b.value)-1))
, ltrim(substring(b.value,charindex('-',b.value)+1,len(b.value)))
FROM [table] a
OUTER APPLY OPENJSON(a.value, '$.arr') b

Если вы хотите, чтобы все значения были в одном столбце, вы можете использовать функцию string_split: https://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql?view=sql-server-2017

SELECT ltrim(rtrim(c.value))
FROM [table] a
OUTER APPLY OPENJSON(a.value, '$.arr') b
OUTER APPLY STRING_SPLIT(b.value, '-') c

Я предпочитаю OPENJSON, а не STRING_SPLIT(), поскольку он возвращается в указанном порядке, что не гарантируется STRING_SPLIT(). CSV легко преобразовать в массив JSON. В моем ответе есть пример.

Shnugo 24.10.2018 17:53

Ах, хороший трюк; манипулировать строкой перед синтаксическим анализом JSON; подлый

JohnLBevan 24.10.2018 17:56

Другие вопросы по теме