Как можно запросить с помощью SQL Server 2017 вложенные значения в JSON? - PullRequest
1 голос
/ 23 апреля 2019

Мне нужно извлечь информацию из столбца в формате JSON с помощью SQL Server. Проблема в том, что он вложен в разные объекты в массиве в объект в массиве - и я как бы сбился с пути. В приведенном ниже примере кода я только дохожу до извлечения массива действий - и затем я застрял. К сожалению, я не слишком знаком с этим.

Я использую SQL Server 2017.

{
    "actions":[
        {
            "class":"actions.entries.class",
            "entries":[
                {
                    "class":"actions.entry.class",
                    "id":null,
                    "key":"BirthDay",
                    "performance":{
                        "class":"actions.entry.performance.class",
                        "origin":null,
                        "originUuid":{
                            "class":"java.util.UUID",
                            "UUID":"3d6c5024-754f-477b-87bc-81d8e5ccadcd"
                        },
                        "performanceDateTime":1556012050827,
                        "performerUuid":{
                            "class":"java.util.UUID",
                            "UUID":"2647a005-a3a8-4362-8f2d-ddd188f500e7"
                        },
                        "registrationDateTime":null,
                        "userUuid":null
                    },
                    "type":"O",
                    "value":"\"2000-01-29T10:34:12.000Z\""
                },
                {
                    "class":"actions.entry.class",
                    "id":null,
                    "key":"Gender",
                    "performance":{
                        "class":"actions.entry.performance.class",
                        "origin":null,
                        "originUuid":{
                            "class":"java.util.UUID",
                            "UUID":"3d6c5024-754f-477b-87bc-81d8e5ccadcd"
                        },
                        "performanceDateTime":1556012050827,
                        "performerUuid":{
                            "class":"java.util.UUID",
                            "UUID":"2647a005-a3a8-4362-8f2d-ddd188f500e7"
                        },
                        "registrationDateTime":null,
                        "userUuid":null
                    },
                    "type":"O",
                    "value":"Female"
                }
            ]
        }
    ]
}

Так, например, мне нужно найти значение ключа «Gender», где значение ключа «BirthDay» не равно нулю: в данном случае «Female». Для ясности я исключил другие объекты в массиве записей.

Любая помощь приветствуется!

Ответы [ 2 ]

1 голос
/ 23 апреля 2019

Вы можете попытаться получить свои данные, используя OPENJSON () . При таком подходе вы можете получить key/value пары из вашего вложенного массива JSON, даже если этот массив имеет разные имена ключей. Вам нужно сослаться на объект или массив JSON с помощью AS JSON.

JSON-ввод:

DECLARE @json nvarchar(max)
SET @json = N'{
    "actions":[
        {
            "class":"actions.entries.class",
            "entries":[
                {
                    "class":"actions.entry.class",
                    "id":null,
                    "key":"BirthDay",
                    "performance":{
                        "class":"actions.entry.performance.class",
                        "origin":null,
                        "originUuid":{
                            "class":"java.util.UUID",
                            "UUID":"3d6c5024-754f-477b-87bc-81d8e5ccadcd"
                        },
                        "performanceDateTime":1556012050827,
                        "performerUuid":{
                            "class":"java.util.UUID",
                            "UUID":"2647a005-a3a8-4362-8f2d-ddd188f500e7"
                        },
                        "registrationDateTime":null,
                        "userUuid":null
                    },
                    "type":"O",
                    "value":"\"2000-01-29T10:34:12.000Z\""
                },
                {
                    "class":"actions.entry.class",
                    "id":null,
                    "key":"Gender",
                    "performance":{
                        "class":"actions.entry.performance.class",
                        "origin":null,
                        "originUuid":{
                            "class":"java.util.UUID",
                            "UUID":"3d6c5024-754f-477b-87bc-81d8e5ccadcd"
                        },
                        "performanceDateTime":1556012050827,
                        "performerUuid":{
                            "class":"java.util.UUID",
                            "UUID":"2647a005-a3a8-4362-8f2d-ddd188f500e7"
                        },
                        "registrationDateTime":null,
                        "userUuid":null
                    },
                    "type":"O",
                    "value":"Female"
                }
            ]
        }
    ]
}'

Получить "Пол" и "День рождения":

SELECT
   t1.[value] AS Birthday,
   t2.[value] AS Gender
FROM OPENJSON(@json, '$.actions')
WITH (
   class nvarchar(max) '$.class',
   entries nvarchar(max) '$.entries' AS JSON
) j
CROSS APPLY OPENJSON(j.entries) 
WITH (
   [key] nvarchar(100) '$.key',
   [value] nvarchar(100) '$.value'
) t1
CROSS APPLY OPENJSON(j.entries) 
WITH (
   [key] nvarchar(100) '$.key',
   [value] nvarchar(100) '$.value'
) t2
WHERE 
   t1.[key] = 'Birthday' AND
   t2.[key] = 'Gender'

Выход:

Birthday                    Gender
"2000-01-29T10:34:12.000Z"  Female

Получить полные данные JSON:

SELECT
   t1.class,
   t2.id, t2.[key], t2.[type], t2.[value],
   t3.class, t3.origin, t3.performanceDateTime, t3.registrationDateTime, t3.userUuid,
   t4.class1, t4.UUID1,
   t5.class2, t5.UUID2
FROM OPENJSON(@json, '$.actions')
WITH (
   class nvarchar(max) '$.class',
   entries nvarchar(max) '$.entries' AS JSON
) t1
CROSS APPLY OPENJSON(t1.entries) 
WITH (
   class nvarchar(1000) '$.class',
   id nvarchar(100) '$.id',
   [key] nvarchar(100) '$.key',
   [type] nvarchar(100) '$.type',
   [value] nvarchar(100) '$.value',
   performance nvarchar(max) '$.performance' AS JSON
) t2
CROSS APPLY OPENJSON (t2.performance) 
WITH (
   class nvarchar(1000) '$.class',
   origin nvarchar(100) '$.origin',
   performanceDateTime nvarchar(100) '$.performanceDateTime',
   registrationDateTime nvarchar(100) '$.registrationDateTime',
   userUuid nvarchar(100) '$.userUuid',
   originUuid nvarchar(max) '$.originUuid' AS JSON,
   performerUuid nvarchar(max) '$.performerUuid' AS JSON
) t3
CROSS APPLY OPENJSON (t3.originUuid) 
WITH (
   class1 nvarchar(1000) '$.class',
   UUID1 nvarchar(100) '$.UUID'
) t4
CROSS APPLY OPENJSON (t3.originUuid) 
WITH (
   class2 nvarchar(1000) '$.class',
   UUID2 nvarchar(100) '$.UUID'
) t5

Выход:

class                   id          key         type    value                       class                               origin  performanceDateTime     registrationDateTime    userUuid    class1          UUID1                                   class2          UUID2
actions.entries.class               BirthDay    O       "2000-01-29T10:34:12.000Z"  actions.entry.performance.class             1556012050827                                               java.util.UUID  3d6c5024-754f-477b-87bc-81d8e5ccadcd    java.util.UUID  3d6c5024-754f-477b-87bc-81d8e5ccadcd
actions.entries.class               Gender      O       Female                      actions.entry.performance.class             1556012050827                                               java.util.UUID  3d6c5024-754f-477b-87bc-81d8e5ccadcd    java.util.UUID  3d6c5024-754f-477b-87bc-81d8e5ccadcd

Обновление:

Если у вас есть данные JSON в качестве значений в столбце таблицы, используйте этот подход для получения данных:

CREATE TABLE #Data (
   JsonData nvarchar(max)
)
INSERT INTO #Data 
   (JsonData)
VALUES 
   (N'{"actions": "value1"}'),
   (N'{"actions": "value2"}')

SELECT *
FROM #Data d
CROSS APPLY OPENJSON(d.JsonData) j

Выход:

JsonData                key     value   type
{"actions": "value1"}   actions value1  1
{"actions": "value2"}   actions value2  1
0 голосов
/ 23 апреля 2019

Дайте мне знать, если это поможет вам.

DECLARE @json nvarchar(max) = N'{
    "actions":[
        {
            "class":"actions.entries.class",
            "entries":[
                {
                    "class":"actions.entry.class",
                    "id":null,
                    "key":"BirthDay",
                    "performance":{
                        "class":"actions.entry.performance.class",
                        "origin":null,
                        "originUuid":{
                            "class":"java.util.UUID",
                            "UUID":"3d6c5024-754f-477b-87bc-81d8e5ccadcd"
                        },
                        "performanceDateTime":1556012050827,
                        "performerUuid":{
                            "class":"java.util.UUID",
                            "UUID":"2647a005-a3a8-4362-8f2d-ddd188f500e7"
                        },
                        "registrationDateTime":null,
                        "userUuid":null
                    },
                    "type":"O",
                    "value":"\"2000-01-29T10:34:12.000Z\""
                },
                {
                    "class":"actions.entry.class",
                    "id":null,
                    "key":"Gender",
                    "performance":{
                        "class":"actions.entry.performance.class",
                        "origin":null,
                        "originUuid":{
                            "class":"java.util.UUID",
                            "UUID":"3d6c5024-754f-477b-87bc-81d8e5ccadcd"
                        },
                        "performanceDateTime":1556012050827,
                        "performerUuid":{
                            "class":"java.util.UUID",
                            "UUID":"2647a005-a3a8-4362-8f2d-ddd188f500e7"
                        },
                        "registrationDateTime":null,
                        "userUuid":null
                    },
                    "type":"O",
                    "value":"Female"
                }
            ]
        }
    ]
}';

SELECT
     [PVT].[action_index]
    ,[CNV].[BirthDay]
    ,[PVT].[Gender]
FROM
(
    SELECT
         [action_index] = [actions].[key]
        ,[entry_field] = [entries].[key]
        ,[entry_value] = [entries].[value]
    FROM OPENJSON(@json, '$.actions') AS [actions] -- iterate over actions array
    OUTER APPLY OPENJSON([actions].[value], '$.entries') -- iterate over entries array for each action
    WITH
    (
         [key] nvarchar(128)
        ,[value] nvarchar(max)
    ) AS [entries]
) AS [SRC]
PIVOT
(
    MAX([entry_value]) FOR [entry_field] IN ([BirthDay], [Gender]) -- pivot the data only for the required fields
) AS [PVT]
CROSS APPLY
(
    SELECT
         [BirthDay] = TRY_CONVERT(datetimeoffset, NULLIF(REPLACE([BirthDay], '"', ''), ''))
) AS [CNV]
WHERE (1 = 1)
    AND ([CNV].[BirthDay] IS NOT NULL);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...