SQL Server Flatten (unknown number of) nested JSON arrays in SQL to return single row, along with parent array

wgeznvg7  于 2023-11-16  发布在  其他
关注(0)|答案(1)|浏览(91)

I have the following (simplified) JSON:

[
    {
        "Workers": [
            {
                "location": "SAP Depot",
                "firstName": "Michael",
                "lastName": "Normanton",
                "sex": "Male",
                "fileOpened": "2018-02-02",
                "risksToBeAwareOf": "I can get dizzy",
                "personID": "3c1ba9ea",
                "documents": [
                    {
                        "docID": "26a41ac0",
                        "name": "MN Contract",
                        "date": "2022-08-15",
                        "Category": "HR"
                    },
                    {
                        "docID": "b5b158c9",
                        "name": "MN RA",
                        "date": "2021-12-17",
                        "Category": "Misc"
                    },
                    {
                        "docID": "b24lk3d8",
                        "name": "MN RA2",
                        "date": "2022-01-17",
                        "Category": "Misc"
                    }
                ]
            }
        ]
    }
]

There is the Workers array, with a number of child objects, though each of these objects can have an unknown number (or none at all) nested arrays called "documents". At the moment, my SQL for importing these from the JSON file is broadly as follows:

SELECT j2.*, j3.* INTO [Workers]

FROM OPENJSON(@JSON) 
WITH
(   
    Workers nvarchar(max) '$.Workers' as JSON
) j1
CROSS APPLY OPENJSON(J1.serviceUsers)
WITH
(       
    FirstName nvarchar(50) '$.firstName',
    LastName nvarchar(75) '$.lastName',
    FileOpened nvarchar(10) '$.fileOpened',
    PersonID nvarchar(100) '$.personID',
    Documents nvarchar(max) '$.documents' as JSON
) j2
OUTER APPLY OPENJSON(J2.Documents)
WITH
(
    dDocID nvarchar(100) '$.docID',
    dDate nvarchar(30) '$.date',
    dName nvarchar(100) '$.name',
    dCategory nvarchar(500) '$.category'
) j3

This displays eg:

FirstName     LastName       FileOpened     PersonID     dDocID      dDate         dName         dCategory
Michael       Normanton      2018-02-02     3c1ba9ea     26a41ac0    2022-08-15    MN Contract   HR
Michael       Normanton      2018-02-02     3c1ba9ea     b5b158c9    2021-12-17    MN RA         Misc
Michael       Normanton      2018-02-02     3c1ba9ea     b24lk3d8    2022-01-17    MN RA2        Misc

Whilst I could say select DISTINCT firstname, lastname, fileopened, personid.... this doesn't feel great for my purposes, and so what I would like it to show (again, there may be more or fewer than three documents for each worker) is something like this:

FirstName  LastName    FileOpened   PersonID   dDocID[1]   dDate[1]     dName[1]      dCategory[1]   dDocID[2]   dDate[2]    dName[2]    dCategory[2]   dDocID[3]      dDate[3]     dName[3]   dCategory[3]
Michael    Normanton   2018-02-02   3c1ba9ea   26a41ac0    2022-08-15   MN Contract   HR             b5b158c9    2021-12-17  MN RA       Misc           b24lk3d8       2022-01-17   MN RA2     Misc
u5rb5r59

u5rb5r591#

Here is an example STATEMENT that may work for you that specifies the structure :

SELECT
    j2.FirstName,
    j2.LastName,
    j2.FileOpened,
    j2.PersonID,
    j3.dDocID AS dDocID1,
    j3.dDate AS dDate1,
    j3.dName AS dName1,
    j3.dCategory AS dCategory1,
    j4.dDocID AS dDocID2,
    j4.dDate AS dDate2,
    j4.dName AS dName2,
    j4.dCategory AS dCategory2,
    j5.dDocID AS dDocID3,
    j5.dDate AS dDate3,
    j5.dName AS dName3,
    j5.dCategory AS dCategory3
INTO [Workers]
FROM OPENJSON(@JSON, '$.Workers')
WITH (
    FirstName nvarchar(50) '$.firstName',
    LastName nvarchar(75) '$.lastName',
    FileOpened nvarchar(10) '$.fileOpened',
    PersonID nvarchar(100) '$.personID',
    Documents nvarchar(max) '$.documents' as JSON
) j2
OUTER APPLY OPENJSON(j2.Documents)
WITH (
    dDocID nvarchar(100) '$.docID',
    dDate nvarchar(30) '$.date',
    dName nvarchar(100) '$.name',
    dCategory nvarchar(500) '$.category'
) j3
OUTER APPLY OPENJSON(j2.Documents, '$[0]')
WITH (
    dDocID nvarchar(100) '$.docID',
    dDate nvarchar(30) '$.date',
    dName nvarchar(100) '$.name',
    dCategory nvarchar(500) '$.category'
) j4
OUTER APPLY OPENJSON(j2.Documents, '$[1]')
WITH (
    dDocID nvarchar(100) '$.docID',
    dDate nvarchar(30) '$.date',
    dName nvarchar(100) '$.name',
    dCategory nvarchar(500) '$.category'
) j5
WHERE j2.FirstName IS NOT NULL

相关问题