Вложенный JSON с использованием FOR JSON PATH
У меня есть несколько таблиц, которые не объединены, но я хочу вернуть данные в виде JSON из запроса с использованием SQL Server с использованием FOR JSON, возможно, с использованием подзапросов?
Создавать таблицы;
DECLARE @Filter AS TABLE
(
filter_id int primary key,
filter_field varchar(255),
filter_values varchar(255)
)
DECLARE @Other AS TABLE
(
other_id int primary key,
other_field varchar(255),
other_values varchar(255)
)
DECLARE @Data AS TABLE
(
data_id int primary key,
Col1 varchar(255),
Col2 varchar(255),
Col3 varchar(255)
)
Вставьте данные;
INSERT INTO @Filter (filter_id, filter_field,filter_values) VALUES
(1, 'SC.Type','Parent'),
(2, 'ScanDateTime','20200620')
INSERT INTO @Other (other_id, other_field,other_values) VALUES
(1, 'header','This is the header'),
(2, 'footer','This is the footer')
INSERT INTO @Data (data_id,Col1,Col2,Col3) VALUES
(1, 'Val1','Val2','Val3'),
(2, 'Val4','Val5','Val6'),
(3, 'Val7','Val8','Val9')
Я постоянно получаю @Filter и @Other, повторяющиеся с каждой строкой @Data.
Каким будет запрос FOR JSON, чтобы получить следующий результат;
{
"filter":
[
{
"field":"SC.Type",
"values":"Parent"
},
{
"field":"ScanDateTime"
"values":"20200620"
}
],
"header":"This is the header",
"footer":"This is the footer",
"data":
[
{
"col1":"Val1",
"col2":"Val2",
"col3":"Val3"
},
{
"col1":"Val4",
"col2":"Val5",
"col3":"Val6"
},
{
"col1":"Val7",
"col2":"Val8",
"col3":"Val9"
}
]
}
Любая помощь будет оценена.
1 ответ
Оригинальный ответ:
Один из возможных подходов - это следующее утверждение:
SELECT
filter = (
SELECT filter_field AS [field], filter_values AS [values]
FROM @filter
FOR JSON AUTO
),
MAX(CASE WHEN other_field = 'header' THEN other_values END) AS header,
MAX(CASE WHEN other_field = 'footer' THEN other_values END) AS footer,
data = (
SELECT Col1, Col2, Col3
FROM @Data
FOR JSON AUTO
)
FROM @Other
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
Результат:
{
"filter":[
{"field":"SC.Type","values":"Parent"},
{"field":"ScanDateTime","values":"20200620"}
],
"header":"This is the header",
"footer":"This is the footer",
"data":[
{"Col1":"Val1","Col2":"Val2","Col3":"Val3"},
{"Col1":"Val4","Col2":"Val5","Col3":"Val6"},
{"Col1":"Val7","Col2":"Val8","Col3":"Val9"}
]
}
Обновить:
Если @Other
таблица имеет более чем header
а также footer
строк и значений этих строк различны (допустимое содержимое JSON или текст), вам нужен смешанный подход с использованием агрегирования строк с STRING_SPLIT()
а также JSON_MODIFY()
:
Таблицы:
DECLARE @Filter AS TABLE
(
filter_id int primary key,
filter_field varchar(255),
filter_values varchar(255)
)
DECLARE @Other AS TABLE
(
other_id int primary key,
other_field varchar(255),
other_values varchar(255)
)
DECLARE @Data AS TABLE
(
data_id int primary key,
Col1 varchar(255),
Col2 varchar(255),
Col3 varchar(255)
)
INSERT INTO @Filter (filter_id, filter_field, filter_values) VALUES
(1, 'SC.Type','Parent'),
(2, 'ScanDateTime','20200620')
INSERT INTO @Other (other_id, other_field, other_values) VALUES
(1, 'header','[{"Row1":"Val1"},{"Row2":"Val2"}]'),
(2, 'footer','This is the footer'),
(3, 'other','Something different')
INSERT INTO @Data (data_id, Col1, Col2, Col3) VALUES
(1, 'Val1','Val2','Val3'),
(2, 'Val4','Val5','Val6'),
(3, 'Val7','Val8','Val9')
Утверждение:
SELECT
JSON_MODIFY(
JSON_MODIFY(
CONCAT(
'{',
STRING_AGG(CONCAT(
'"',
other_field ,
'":',
CASE WHEN ISJSON(other_values) = 1 THEN other_values ELSE CONCAT('"', other_values, '"') END,
''
), ','),
'}'
),
'$.filter',
JSON_QUERY((
SELECT filter_field AS [field], filter_values AS [values]
FROM @filter
FOR JSON AUTO
))
),
'$.data',
JSON_QUERY((
SELECT Col1, Col2, Col3
FROM @Data
FOR JSON AUTO
))
)
FROM @Other
Результат:
{
"header":[
{
"Row1":"Val1"
},
{
"Row2":"Val2"
}
],
"footer":"This is the footer",
"other":"Something different",
"filter":[
{
"field":"SC.Type",
"values":"Parent"
},
{
"field":"ScanDateTime",
"values":"20200620"
}
],
"data":[
{
"Col1":"Val1",
"Col2":"Val2",
"Col3":"Val3"
},
{
"Col1":"Val4",
"Col2":"Val5",
"Col3":"Val6"
},
{
"Col1":"Val7",
"Col2":"Val8",
"Col3":"Val9"
}
]
}