web-dev-qa-db-fra.com

Comment analyser un tableau JSON imbriqué à l'aide de SQL Server

Je suis actuellement en mesure d'analyser la plupart des fichiers JSON à l'aide de la syntaxe "OPENJSON WITH (...") de SQL Server. Toutefois, ce fichier contient des tableaux imbriqués que je ne sais pas comment gérer.

La plupart des exemples que j'ai lus font référence à JSON en tant que variable. Dans ce cas, j'appelle un fichier:

select DEV_JSON.*
from OPENROWSET
(BULK 'C:\Users\Myuser\Documents\JSON_extract.json', SINGLE_CLOB) as my_datafile
 CROSS APPLY OPENJSON(BulkColumn) 
WITH
  (DOC_ID           varchar(100)  '$.doc._id',
   DOC_REV          varchar(45)   '$.doc._rev',
   DELY_APPL_NAME   varchar(20)   '$.doc.delivery.application',
   DELY_SENT_BY     varchar(25)   '$.doc.delivery.sender.id',
   DELY_SENT_TYPO   varchar(20)   '$.doc.delivery.sender.type',
   .....
   ....
   ...
   ..) as DEV_JSON

L'un des attributs contient un tableau imbriqué. Ci-dessous, j'ai copié les 5 premiers attributs de mon JSON, ainsi que le tableau "destinataires" imbriqué. 

Comment structurer mon SQL pour analyser cette section?

"doc": {
    "_id": "[email protected]",
    "_rev": "3-e119db13dae8d50ae0c4579ba9c87fc9",
    "delivery": {
        "application": "App_XYZ",
        "sender": {
            "id": "[email protected]",
            "type": "user"
        },
        "recipients": [{
                "type": "email",
                "recipient": "\"Artzer, Daniel J\" <[email protected]>",
                "sentTS": "2017-10-18T13:04:00.133Z"
            },
            {
                "type": "email",
                "recipient": "\"Higgins, Laura L\" <[email protected]>",
                "sentTS": "2017-10-18T13:04:00.133Z"
            },
            {
                "type": "email",
                "recipient": "\"Friedman, Brian\" <[email protected]>",
                "sentTS": "2017-10-18T13:04:00.133Z"
            },
            {
                "type": "email",
                "recipient": "\"Garcia, Charlie M\" <[email protected]>",
                "sentTS": "2017-10-18T13:04:00.133Z"
            }
        ]
    },
4
CarCrazyBen

Je viens d'avoir le même problème et j'ai fini par le résoudre avec plusieurs clauses CROSS APPLY. 

Voici un exemple de mon JSON:

DECLARE @PermsJSON NVARCHAR(MAX) =
N'[{
    "AppId": 1,
    "Perms":
    [{

        "Permission": ["AA", "BB"],
        "PermissionTypeID": 2
    },
    {
        "Permission": ["10"],
        "PermissionTypeID": 1
    }]
},
{
    "AppId": 2,
    "Perms":
    [{

        "Permission": ["IM", "NM"],
        "PermissionTypeID": 2
    },
    {
        "Permission": ["42"],
        "PermissionTypeID": 1
    }]
}]';

Et puis je peux l'analyser en utilisant la requête suivante:

SELECT
    a.AppId
    ,[Permission] = c.Value
    ,b.PermissionTypeID
FROM
    OPENJSON(@PermsJSON)
    WITH
        (
            AppId INT N'$.AppId'
            ,Perms NVARCHAR(MAX) AS JSON
        ) AS a
CROSS APPLY
    OPENJSON(a.Perms)
    WITH
        (
            PermissionTypeID INT
            ,[Permission] NVARCHAR(MAX) AS JSON
        ) AS b
CROSS APPLY OPENJSON(b.Permission) AS c;

Les résultats ressemblent alors à ceci:

AppId   Permission  PermissionTypeID
1       AA          2
1       BB          2
1       10          1
2       IM          2
2       NM          2
2       42          1
6
digital.aaron

Après BEAUCOUP recherches, j'ai finalement découvert la réponse à ce problème. Je dois simplement inclure le tableau imbriqué comme une autre colonne JSON dans ma requête, comme ceci:

WITH
 (DOC_ID                varchar(100)  '$.doc._id',
  DOC_REV               varchar(45)   '$.doc._rev',
  DELY_APPL_NAME        varchar(20)   '$.doc.delivery.application',
  DELY_SENT_BY          varchar(25)   '$.doc.delivery.sender.id',
  DELY_SENT_TYPO        varchar(20)   '$.doc.delivery.sender.type',
  RECIPS                nvarchar(max) '$.doc.delivery.recipients' as JSON,
  PAYLOAD_START_TIME    varchar(30)   '$.doc.payload.startTS',
  ....
  ...
  ..
  ) as my_query

Je me retrouve donc avec un enregistrement par document JSON, avec (dans ce cas) une colonne varchar contenant du texte JSON. 

Ensuite, je peux exécuter une requête distincte sur cette colonne pour analyser le JSON et créer une "table enfant" associée au parent.

1
CarCrazyBen