web-dev-qa-db-ja.com

SQL Serverを使用してネストされたJSON配列を解析する方法

現在、SQL Serverの「OPENJSON WITH(...」構文を使用してJSONファイルのほとんどを解析できます。ただし、この特定のファイルには、処理方法がわからないネストされた配列が含まれています。

私が読んだ例の多くは、変数としてJSONを参照しています。この場合、ファイルを呼び出しています:

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

属性の1つにネストされた配列が含まれています。以下に、JSONの最初の5つの属性と、ネストされた「受信者」配列をコピーしました。

このセクションを解析するためにSQLをどのように構成しますか?

"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"
            }
        ]
    },
8
CarCrazyBen

私は同じ問題を抱えていましたが、複数のCROSS APPLY句を使用して解決しました。

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
    }]
}]';

そして、次のクエリを使用して解析できます。

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;

結果は次のようになります。

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

[〜#〜] much [〜#〜]検索の後、私はついにこの問題の答えを発見しました。次のように、ネストされた配列をクエリの別のJSON列として含める必要があります。

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

そのため、JSONドキュメントごとに1つのレコードが作成され、(この場合)JSONテキストを含むvarchar列があります。

次に、この列に対して別のクエリを実行してJSONを解析し、親に関連付けられた「子テーブル」を作成できます。

1
CarCrazyBen