Вы не указали ожидаемый результат. То, что у меня есть: вы хотите получить то же, что и выше, без необходимости буквально указывать имена. Надеюсь, я правильно понял:
SELECT JSON_VALUE(A.[value],'$.ID') AS ID
,JSON_VALUE(A.[value],'$.Measure') AS Measure
,B.[key] AS [varName]
,B.[value] AS [varValue]
,ROW_NUMBER() OVER(PARTITION BY JSON_VALUE(A.[value],'$.ID') ORDER BY B.[key]) RowIndex
FROM OPENJSON(@json) A
CROSS APPLY OPENJSON(A.[value]) B
WHERE b.[key] NOT IN('ID','Measure');
Результат
+----+---------------+------------+----------+----------+
| ID | Measure | varName | varValue | RowIndex |
+----+---------------+------------+----------+----------+
| 1 | Current Sales | 2019Week12 | 33 | 1 |
+----+---------------+------------+----------+----------+
| 1 | Current Sales | 2019Week13 | 33 | 2 |
+----+---------------+------------+----------+----------+
| 1 | Current Sales | 2019Week14 | 34 | 3 |
+----+---------------+------------+----------+----------+
| 2 | Current Sales | 2019Week12 | | 1 |
+----+---------------+------------+----------+----------+
| 2 | Current Sales | 2019Week13 | 10 | 2 |
+----+---------------+------------+----------+----------+
| 2 | Current Sales | 2019Week14 | 60 | 3 |
+----+---------------+------------+----------+----------+
Идея вкратце:
- Мы используем
OPENJSON()
, чтобы погрузиться в ваш json строка Это вернет два объекта, содержащихся в производном наборе A
. - Теперь мы снова используем
OPENJSON()
, передавая A.[value]
, то есть сам объект json. - Это вернул бы все содержащиеся в нем элементы, но мы исключаем
ID
и Measurement
в пределах WHERE
. - Два специальных столбца,
ID
и Measurement
, мы выбираем непосредственно из A.[value]
, используя JSON_VALUE()
.
ОБНОВЛЕНИЕ
Одним из усовершенствований может быть следующее:
SELECT C.ID
,C.varName AS [varName]
,TRY_CAST(LEFT(C.varName,4) AS INT) AS MeasureYear
,TRY_CAST(RIGHT(C.varName,2) AS INT) AS MeasureWeek
,C.varContent AS [varValue]
,ROW_NUMBER() OVER(PARTITION BY C.ID ORDER BY C.varName) RowIndex
FROM OPENJSON(@json) A
CROSS APPLY OPENJSON(A.[value]) B
CROSS APPLY (SELECT JSON_VALUE(A.[value],'$.ID') AS ID
,JSON_VALUE(A.[value],'$.Measure') AS Measure
,B.[key] AS varName
,B.[value] AS varContent) C
WHERE C.varName NOT IN('ID','Measure');
Идея: добавление еще одного APPLY
позволяет возвращать значения как обычные столбцы . Это облегчает работу со значениями и делает этот лот более читабельным.