【问题标题】:JSON to SQL - Extracting from JSON Array?JSON 到 SQL - 从 JSON 数组中提取?
【发布时间】:2019-07-27 03:05:47
【问题描述】:

我有一个练习要从一个较大的 JSON 对象中提取一些数据,但是这些数据是作为多个对象添加的,或者可能是一个数组。

下面的例子;

DECLARE @json NVARCHAR(MAX) = '{
"N.data.-ce731645-e4ef-4784-bc02-bb90b4c9e9e6": "Some Data",
"N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f": [
    {
        "date_1": "2018-10-20T23:00:00.000Z"
    },
    {
        "date_1": "2018-10-21T23:00:00.000Z"
    }
]
}'

我需要将这些日期时间条目从“date_1”标识符中提取到理想情况下的 CSV 列表中。从中我可以进行自己的操作。

2018-10-20T23:00:00.000Z, 2018-10-21T23:00:00.000Z

我熟悉 JSON_VALUE(),但不熟悉它在简单的一维数据之外的使用。

到目前为止我所拥有的;

DECLARE @json NVARCHAR(MAX) = '{
"N.data.-ce731645-e4ef-4784-bc02-bb90b4c9e9e6": "Some Data",
"N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f": [
    {
        "date_1": "2018-10-20T23:00:00.000Z"
    },
    {
        "date_1": "2018-10-21T23:00:00.000Z"
    }
]
}'

SELECT value FROM OPENJSON(@json)

有没有办法在复杂的 substring() 和 replace() 使用之外实现预期的输出?

使用 SQL Server 2017

Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64)   Aug 22 2017 17:04:49   Copyright (C) 2017 Microsoft Corporation  Express Edition (64-bit) on Windows Server 2012 R2 Datacenter 6.3 <X64> (Build 9600: ) (Hypervisor) 

谢谢

【问题讨论】:

    标签: sql json sql-server extract


    【解决方案1】:

    从SQL Server 2017开始,可以通过原生OPENJSON进行提取:

    DECLARE @json NVARCHAR(MAX) = '{
    "N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f": [
        {
            "date_1": "2018-10-20T23:00:00.000Z"
        },
        {
            "date_1": "2018-10-21T23:00:00.000Z"
        }
    ]
    }'
    
    
    SELECT  
        JSON_VALUE(child_value.value, '$.date_1') AS [key]    
    FROM OPENJSON(@json, '$') AS nda
    cross apply openjson(nda.value, '$') as child_value
    

    结果:

    key
    2018-10-20T23:00:00.000Z
    2018-10-21T23:00:00.000Z
    

    有没有办法调整它以提取特定的值 键,“N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f”在 例子

    在这种情况下,该查询可以稍微简化为:

    DECLARE @id nvarchar(200) = 'N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f'
    
    SELECT  
        JSON_VALUE(nda.value, '$.date_1') AS [key]    
    FROM OPENJSON(@json, concat('$."',@id,'"')) AS nda
    

    或者没有参数化:

    SELECT  
        JSON_VALUE(nda.value, '$.date_1') AS [key]    
    FROM OPENJSON(@json, '$."N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f"') AS nda
    

    【讨论】:

    • 感谢您,这正是解决问题的代码。问题是我没有包含 JSON 的真实示例。我已经编辑了我的问题。 JSON 将包含多个键。有没有办法调整它以提取特定键的值,例如“N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f”。
    • @Bert682,我已经更新了答案,这个新要求也会使其执行速度略快
    • 谢谢,完美:)
    【解决方案2】:

    使用 with_clause 与 OPENJSON() 交叉应用:

    DECLARE @json NVARCHAR(MAX) = '{
    "N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f": [
        {
            "date_1": "2018-10-20T23:00:00.000Z"
        },
        {
            "date_1": "2018-10-21T23:00:00.000Z"
        }
    ]
    }';
    
    SELECT [b].*
    FROM   OPENJSON(@json) [a]
    CROSS APPLY
           OPENJSON([a].[Value])
               WITH (
                        [date_1] DATETIME '$.date_1'
                    ) [b];
    

    【讨论】:

    • 感谢您的评论,但我也尝试过,但结果为空。无论如何,您和我似乎想出了相同的解决方案,并且由于您首先发布了您的解决方案,因此我删除了我的解决方案并投票赞成您的解决方案。
    【解决方案3】:

    另一种可能的方法,使用OPENJSON()。使用这种方法,您可以从嵌套的 JSON 数组中获取 key/value 对,即使该数组具有不同的键名。

    DECLARE @json nvarchar(max)
    SET @json = 
    N'{"N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f": [
        {
            "date_1": "2018-10-20T23:00:00.000Z"
        },
        {
            "date_1": "2018-10-21T23:00:00.000Z"
        },
        {
            "date_2": "2019-10-21T23:00:00.000Z"
        }
    ]
    }'
    
    SELECT 
       x.[key] AS SessionData, 
       z.[key],
       z.[value]
    FROM OPENJSON(@json) x
    CROSS APPLY (SELECT * FROM OPENJSON(x.[value])) y
    CROSS APPLY (SELECT * FROM OPENJSON(y.[value])) z
    --WHERE z.[key] = 'date_1'
    

    输出:

    SessionData                                                 key     value
    N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f    date_1  2018-10-20T23:00:00.000Z
    N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f    date_1  2018-10-21T23:00:00.000Z
    N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f    date_2  2019-10-21T23:00:00.000Z
    

    更新: 如果您想按键名过滤,下一步可能会有所帮助:

    DECLARE @json NVARCHAR(MAX) = '{
    "N.data.-ce731645-e4ef-4784-bc02-bb90b4c9e9e6": "Some Data",
    "N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f": [
        {
            "date_1": "2018-10-20T23:00:00.000Z"
        },
        {
            "date_1": "2018-10-21T23:00:00.000Z"
        }
    ]
    }'
    
    SELECT z.[value]
    --SELECT STRING_AGG(z.[value], ', ') [Data] -- with string aggregation
    FROM OPENJSON(@json) x
    CROSS APPLY (SELECT * FROM OPENJSON(x.[value])) y
    CROSS APPLY (SELECT * FROM OPENJSON(y.[value])) z
    WHERE x.[key] = 'N.data.sessionDates-7f1790d3-9175-43aa-962b-161ee3b8615f'
    

    输出:

    value
    2018-10-20T23:00:00.000Z
    2018-10-21T23:00:00.000Z
    -- With string aggregation
    --Data
    --2018-10-20T23:00:00.000Z, 2018-10-21T23:00:00.000Z
    

    【讨论】:

      猜你喜欢
      • 2019-04-21
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-05
      相关资源
      最近更新 更多