繁体   English   中英

如何使用 SQL Server 2017 查询 JSON 中的嵌套值?

[英]How can I query with SQL Server 2017 for nested values in JSON?

我必须使用 SQL Server 从 JSON 格式的列中提取信息。 问题是它嵌套在数组中的一个对象中的一个数组中的不同对象中 - 我有点迷失了方向。 在下面的代码示例中,我只提取了动作数组 - 然后我被卡住了。 不幸的是,我对这个不太熟悉。

我使用 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”。 为了清楚起见,我省略了条目数组中的其他对象。

欢迎任何帮助!

您可以尝试使用OPENJSON()获取数据。 通过这种方法,您可以从嵌套的JSON数组中获取key/value对,即使该数组具有不同的键名。 您需要的是使用AS JSON子句引用 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

如果这对您有帮助,请告诉我。

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM