Home > front end >  SQL Server - parse json with multiple objects
SQL Server - parse json with multiple objects

Time:06-21

I'm parsing a JSON dataset within SQL Server and it works great with a single object, but falls down when multiple data objects are presented. I assume it's because of the CROSS APPLY statements.

Within the JSON dataset, there is only 4 records, but my current sql is returning 16 (4 duplicate sets, as there are 4 cross apply statements), but I'm not sure how to get around this?

json

{
    "type": "test",
    "user": {
        "last_update": "2022-06-19T14:13:07.707502 00:00",
        "user_id": "12345"
    },
    "data": [
        {
            "metadata": {
                "start_time": "2022-06-19T00:00:00 01:00",
                "end_time": "2022-06-20T00:00:00 01:00"
            },
            "distance_data": {
                "steps": 9299,
                "distance_meters": 7704.0
            }
        },
        {
            "metadata": {
                "start_time": "2022-06-17T00:00:00 01:00",
                "end_time": "2022-06-18T00:00:00 01:00"
            },
            "distance_data": {
                "steps": 2546,
                "distance_meters": 2143.0
            }
        },
        {
            "metadata": {
                "start_time": "2022-06-16T00:00:00 01:00",
                "end_time": "2022-06-17T00:00:00 01:00"
            },
            "distance_data": {
                "steps": 4969,
                "distance_meters": 4192.0
            }
        },
        {
            "metadata": {
                "start_time": "2022-06-18T00:00:00 01:00",
                "end_time": "2022-06-19T00:00:00 01:00"
            },
            "distance_data": {
                "steps": 6769,
                "distance_meters": 5698.0
            }
        }
    ]
}

SQL statement

    SELECT
    distance_meters, steps, cast(left(start_time,10) as date) startDate
    FROM  
     OPENJSON ( @json )  
WITH (          
            jType nvarchar(50) N'$.type',
            jUser char(36) N'$.user.user_id',       
            data nvarchar(max) as JSON
        ) as a
        CROSS APPLY
            OPENJSON(a.data)
            WITH
            (
                distance_data nvarchar(max) as json
            ) as b
        CROSS APPLY
            OPENJSON (b.distance_data)
            WITH 
            (
            distance_meters float,
            steps int
            ) as c
        CROSS APPLY
            OPENJSON (a.data)
            WITH
            (
                metadata nvarchar(max) as json
            ) as d
        CROSS APPLY
            OPENJSON (d.metadata)
            WITH 
            (
                start_time nvarchar(25),    
                end_time nvarchar(25)
            ) as e
        ORDER BY startDate ASC;

CodePudding user response:

I think you need a single APPLY operator:

SELECT j1.jType, j1.jUser, j2.*
FROM OPENJSON(@json) WITH (          
   jType nvarchar(50) N'$.type',
   jUser char(36) N'$.user.user_id',       
   data nvarchar(max) as JSON
) AS j1
CROSS APPLY OPENJSON(j1.data) WITH (
   start_time nvarchar(25) '$.metadata.start_time',
   end_time nvarchar(25) '$.metadata.end_time',
   steps numeric(10, 0) '$.distance_data.steps',
   distance_meters numeric(10, 1) '$.distance_data.distance_meters'
) j2

Result:

jType jUser start_time end_time steps distance_meters
test 12345 2022-06-19T00:00:00 01:00 2022-06-20T00:00:00 01:00 9299 7704.0
test 12345 2022-06-17T00:00:00 01:00 2022-06-18T00:00:00 01:00 2546 2143.0
test 12345 2022-06-16T00:00:00 01:00 2022-06-17T00:00:00 01:00 4969 4192.0
test 12345 2022-06-18T00:00:00 01:00 2022-06-19T00:00:00 01:00 6769 5698.0
  • Related