【问题标题】:How to flatten nested array from JSON in SQL Server如何在 SQL Server 中展平来自 JSON 的嵌套数组
【发布时间】:2022-12-17 22:14:17
【问题描述】:

我正在尝试使用下面的代码在 SQL Server 中展平来自 JSON 的嵌套数组,但没有成功。

使用的 JSON

'{
    "shipmentDetails": {
        "shipmentId": "JHVJD5627278788"
    },
    "shipmentStops": [
        {
            "stopSequence": 1,
            "orderReferenceNumbers": [
                "2120549020", "test"
            ]
        },
        {
            "stopSequence": 2,
            "orderReferenceNumbers": [
                "2120549020", "2120549002"
            ]
        }
    ]
}'
DECLARE @Step AS NVARCHAR(max) = N'Variables declaration';
DECLARE @JSON1 AS NVARCHAR(MAX);

SET @JSON1 = '{
    "shipmentDetails": {
        "shipmentId": "JHVJD5627278788"
    },
    "shipmentStops": [
        {
            "stopSequence": 1,
            "orderReferenceNumbers": [
                "2120549020", "test"
            ]
        },
        {
            "stopSequence": 2,
            "orderReferenceNumbers": [
                "2120549020", "2120549002"
            ]
        }
    ]
}'

IF OBJECT_ID('JSONPO2') IS NOT NULL
    DROP TABLE JSONPO2

SET @Step = N'JSON data parsing and loading into JSONPO2 temp table'

SELECT DISTINCT ShipDetails.shipmentId AS shipmentId
    ,ShipmentStops.stopSequence AS stopSequence
    ,ShipmentStops.orderReferenceNumbers AS orderReferenceNumbers
INTO JSONPO2
FROM OPENJSON(@JSON1) WITH (
        shipmentDetails NVARCHAR(MAX) AS JSON
        ,shipmentStops NVARCHAR(MAX) AS JSON
        ) AS [Data]
CROSS APPLY OPENJSON(shipmentDetails) WITH (shipmentId NVARCHAR(20)) AS ShipDetails
CROSS APPLY OPENJSON(shipmentStops) WITH (
        stopSequence INT
        ,orderReferenceNumbers NVARCHAR(MAX) AS JSON
        ) AS ShipmentStops
CROSS APPLY OPENJSON(orderReferenceNumbers) WITH (orderReferenceNumbers VARCHAR(max)) 
AS orderReferenceNumbers

SELECT *
FROM JSONPO2

从上面的代码中,我只收到两行带有一个奇怪的数组

shipmentId stopSequence orderReferenceNumbers
JHVJD5627278788 1 [
"2120549020", "test"
]
JHVJD5627278788 2 [
"2120549020", "2120549002"
]

如何更改代码以解析嵌套数组并有如下四行?

shipmentId stopSequence orderReferenceNumbers
JHVJD5627278788 1 2120549020
JHVJD5627278788 1 test
JHVJD5627278788 2 2120549020
JHVJD5627278788 2 2120549002

感谢任何帮助:)

【问题讨论】:

    标签: sql json sql-server


    【解决方案1】:

    您的问题是在尝试使用 WITH 子句扩展数组时:

    CROSS APPLY OPENJSON(orderReferenceNumbers) 
       WITH (orderReferenceNumbers VARCHAR(max)) AS orderReferenceNumbers
    

    您打开的 JSON 没有属性“orderReferenceNumbers”,它只是:

    [“2120549020”,“测试”]

    所以这是返回NULL。如果您选择 orderReferenceNumbers.orderReferenceNumbers 而不是 ShipmentStops.orderReferenceNumbers,您会在选择中看到它。

    如果您打开一个简单的原始类型 JSON 数组,则不需要使用 WITH。以下查询将返回您之后的输出:

    DECLARE @JSON1 AS NVARCHAR(MAX) = N'{
        "shipmentDetails": {
            "shipmentId": "JHVJD5627278788"
        },
        "shipmentStops": [
            {
                "stopSequence": 1,
                "orderReferenceNumbers": [
                    "2120549020", "test"
                ]
            },
            {
                "stopSequence": 2,
                "orderReferenceNumbers": [
                    "2120549020", "2120549002"
                ]
            }
        ]
    }';
    
    SELECT  sd.shipmentId, 
            ss.stopSequence, 
            orderReferenceNumber = orn.Value
    FROM    OPENJSON(@JSON1)
                WITH(shipmentDetails NVARCHAR(MAX) AS JSON, shipmentStops NVARCHAR(MAX) AS JSON) AS d
            CROSS APPLY OPENJSON(d.shipmentDetails)
                WITH(shipmentId NVARCHAR(20)) AS sd
            CROSS APPLY OPENJSON(d.shipmentStops)
                WITH(stopSequence INT, orderReferenceNumbers NVARCHAR(MAX) AS JSON) AS ss
            CROSS APPLY OPENJSON(orderReferenceNumbers) AS orn;
    

    Example on db<>fiddle

    顺便说一句,如果您在 JSON 中只有一个 shipmentId(这是有意义的,否则您最终会得到交叉连接),您可以稍微简化一下,并删除其中一个 OPENJSON()s:

    SELECT  d.shipmentId, 
            ss.stopSequence, 
            orderReferenceNumber = orn.Value
    FROM    OPENJSON(@JSON1)
                WITH(ShipmentId NVARCHAR(20) '$.shipmentDetails.shipmentId', 
                    shipmentStops NVARCHAR(MAX) AS JSON) AS d
            CROSS APPLY OPENJSON(d.shipmentStops)
                WITH(stopSequence INT, orderReferenceNumbers NVARCHAR(MAX) AS JSON) AS ss
            CROSS APPLY OPENJSON(ss.orderReferenceNumbers) AS orn;
    

    【讨论】:

      猜你喜欢
      • 2021-10-12
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 2014-08-29
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多