Используя TSQL OPENJSON, как извлечь значение из массива JSON с именем динамического ключа - PullRequest
2 голосов
/ 16 апреля 2019

У меня есть документ JSON с внутренним массивом атрибутов. На одном из этих атрибутов имя ключа изменяется динамически / случайным образом. Я могу легко извлечь все точки данных за исключением этого последнего неприятного атрибута. Все методы, которые я нашел или использовал в прошлом с OPENJSON, основывались на известном имени ключа.

Внутри «внутреннего» массива первый атрибут будет иметь имя ключа, которое изменяется. Я хочу извлечь значение, связанное с этим динамическим ключом, не зная точно, каким будет этот ключ. Надеемся, что приведенный ниже код опишет проблему лучше, чем я, со словами.

Вот как выглядит документ JSON, отформатированный для удобства чтения ...

{
    "outer1": {
        "inner1": {
            "dynamicKey123": "attribute1",
            "staticKey1": "attribute2",
            "staticKey2": "attribute3",
            "staticKey3": "attribute4"
        }
    },
    "outer2": {
        "inner2": {
            "dynamicKeyABC": "attribute1",
            "staticKey1": "attribute2",
            "staticKey2": "attribute3",
            "staticKey3": "attribute4"
        }
    }
}

Код для проверки ...

CREATE TABLE openjson_test (json_col VARCHAR(MAX));

INSERT INTO openjson_test (json_col)
VALUES ('{"outer1":{"inner1":{"dynamicKey123":"attribute1","staticKey1":"attribute2","staticKey2":"attribute3","staticKey3":"attribute4"}},"outer2":{"inner2":{"dynamicKeyABC":"attribute1","staticKey1":"attribute2","staticKey2":"attribute3","staticKey3":"attribute4"}}}');

Вопрос, который я разработал до сих пор с проблемными частями, закомментирован ...

SELECT
    json_col,
    so.[key] AS soKey,
    si.[key] AS siKey,
    si.[value] AS siValue,
    --ar.dynamicKey, 
    ar.staticKey1,
    ar.staticKey2,
    ar.staticKey3
FROM openjson_test
CROSS APPLY OPENJSON(json_col) so
CROSS APPLY OPENJSON(json_col, '$.' + so.[key]) si
CROSS APPLY OPENJSON(json_col, '$.' + so.[key] + '.' + si.[key])
WITH (
    --dynamicKey VARCHAR(256) '$.dynamicKey???', How do I extract this value without knowing the key
    staticKey1 VARCHAR(256) '$.staticKey1',
    staticKey2 VARCHAR(256) '$.staticKey2',
    staticKey3 VARCHAR(256) '$.staticKey3'
) ar

Ответы [ 2 ]

0 голосов
/ 17 апреля 2019

Я бы предложил подход с условной агрегацией

SELECT
    so.[key] AS soKey,
    si.[key] AS siKey,
    MAX(CASE WHEN attr.[key] NOT IN('staticKey1','staticKey2','staticKey3') THEN attr.[value] END) AS DynamicAttr,
    MAX(CASE WHEN attr.[key]='staticKey1' THEN attr.[value] END) AS attrKey1,
    MAX(CASE WHEN attr.[key]='staticKey2' THEN attr.[value] END) AS attrKey2,
    MAX(CASE WHEN attr.[key]='staticKey3' THEN attr.[value] END) AS attrKey3
FROM openjson_test
CROSS APPLY OPENJSON(json_col) so
CROSS APPLY OPENJSON(json_col, '$.' + so.[key]) si
CROSS APPLY OPENJSON(json_col, '$.' + so.[key] + '.' + si.[key]) attr
GROUP BY so.[key],si.[key];

Этот метод используется в PIVOT сценариях, но допускает более общую логику.

0 голосов
/ 17 апреля 2019

Вы можете использовать OPENJSON без предложения WITH и отфильтровать столбец с известными именами:

SELECT json_col,
    so.[key] AS soKey,
    si.[key] AS siKey,
    si.[value] AS siValue,
    ar2.Value AS dynamicKey,
    ar.staticKey1,
    ar.staticKey2,
    ar.staticKey3
FROM dbo.openjson_test t
CROSS APPLY OPENJSON(t.json_col) so
CROSS APPLY OPENJSON(json_col, '$.' + so.[key]) si
CROSS APPLY OPENJSON(json_col, '$.' + so.[key] + '.' + si.[key])
WITH (
    staticKey1 VARCHAR(256) '$.staticKey1',
    staticKey2 VARCHAR(256) '$.staticKey2',
    staticKey3 VARCHAR(256) '$.staticKey3'
) ar
CROSS APPLY (
    SELECT *
    FROM OPENJSON(json_col, '$.' + so.[key] + '.' + si.[key])
    WHERE [Key] NOT IN ('staticKey1','staticKey2','staticKey3')
) ar2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...