Вложенный JSON с использованием FOR JSON PATH - PullRequest
0 голосов
/ 19 июня 2020

У меня есть несколько таблиц, которые не объединены, но я хочу вернуть данные как JSON из запроса, используя SQL Server, используя FOR JSON, возможно, используя подзапросы?

Create table;

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.

Что бы быть запросом ДЛЯ 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 Ответ

0 голосов
/ 20 июня 2020

Исходный ответ:

Одним из возможных подходов является следующий оператор:

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"
    }
  ]
}
...