sql >> データベース >  >> RDS >> Sqlserver

SQL Serverのキーと値のペア(EAV形式)のリストにJSONを読み込みます

    まず、宣言されたテーブル変数を作成し、問題をシミュレートするためにいくつかのサンプルJSONを入力します(配列のJSONパスを反映するためにサンプルにいくつかの配列を追加しました):

    DECLARE @table TABLE(ID INT IDENTITY, AnyJSON NVARCHAR(MAX));
    INSERT INTO @table VALUES
    (N' {
        "correlationId": "c3xOeEEQQCCA9sEx7-u6FA",
        "eventCreateTime": "2020-05-12T15:38:23.717Z",
        "time": 1589297903717,
        "owner": {
            "ownergeography": {
                "city": "abc",
                "country": "abc"
            },
            "ownername": {
                "firstname": "abc",
                "lastname": "def"
            },
            "clientApiKey": "xxxxx",
            "businessProfileApiKey": null,
            "userId": null
        },
        "campaignType": "Mobile push"
    }')
    ,(N'[{
        "correlationIds": [
            {
                "campaignId": [1,2,3],
                "correlationId": [{"a":"b"},{"c":"d"},{"e":"f"}]
            }
        ],
        "variantId": 1278915,
        "utmCampaign": "",
        "ua.os.major": "8"
        }
        ,{
        "correlationIds": [
            {
                "campaignId": [1,2,3],
                "correlationId": [{"a":"b"},{"c":"d"},{"e":"f"}]
            }
        ],
        "variantId": 1278915,
        "utmCampaign": "",
        "ua.os.major": "8"
        }]')
    ,(N'{
        "correlationId": "ls7XmuuiThWzktUeewqgWg",
        "eventCreateTime": "2020-05-12T12:40:20.786Z",
        "time": 1589287220786,
        "modifiedBy": {
            "clientId": null,
            "clientApiKey": "xxx",
            "businessProfileApiKey": null,
            "userId": null
        },
        "campaignType": "Mobile push"
    }');
    

    -クエリ

    WITH recCTE AS
    (
        SELECT ID
              ,NestLevel   = 0 
              ,ObjectIndex = CAST(1 AS bigint)                                                          
              ,SortString  = CAST(N'sort'                       COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX)) 
    
              ,JsonPath    = CAST(N'$'                          COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX))
              ,JsonKey     = CAST(N'$'                          COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX)) 
              ,JsonValue   = CAST(AnyJSON                       COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX)) 
              ,JsonType    = CAST(CASE WHEN LEFT(TRIM(AnyJSON),1)=N'[' THEN 4 ELSE 0 END AS TINYINT)
              ,NestedJSON  = CAST(CASE WHEN ISJSON(AnyJSON)=1 
                                       THEN AnyJSON 
                                       ELSE NULL END            COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX)) 
        FROM @table t
    
        UNION ALL
    
        SELECT r.ID
              ,r.NestLevel+1
              ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) 
              ,CAST(CONCAT(r.SortString,REPLACE(STR(ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),5),' ','0')) COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX))
    
              ,CAST(CONCAT(r.JsonPath, CASE WHEN r.JsonType=4 --<-- see the docs for OPENJSON()
                                            THEN CONCAT('[',A.[key],']') 
                                            ELSE '.' + A.[key] END)                       COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX))
              ,CAST(A.[key]                                                               COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX))
              ,CAST(r.JsonValue                                                           COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX))
              ,A.[type] 
              ,CAST(A.[value]                                                             COLLATE DATABASE_DEFAULT AS NVARCHAR(MAX))
        FROM recCTE r
        CROSS APPLY OPENJSON(r.NestedJSON) A
        WHERE ISJSON(r.NestedJSON)=1
    )
    SELECT ID
          ,NestLevel
          ,ObjectIndex
          ,JsonPath
          ,JsonKey
          ,NestedJSON AS JsonValue
          ,SortString --<-- just to illustrate the sorting, not needed in the output
    FROM recCTE 
    WHERE ISJSON(NestedJSON)=0
    ORDER BY ID,SortString;
    

    結果

    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | ID | JsonPath                                  | JsonKey         | JsonValue                | SortString                      |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 1  | $.correlationId                           | correlationId   | c3xOeEEQQCCA9sEx7-u6FA   | 0    1                          |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 1  | $.eventCreateTime                         | eventCreateTime | 2020-05-12T15:38:23.717Z | 0    2                          |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 1  | $.time                                    | time            | 1589297903717            | 0    3                          |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 1  | $.owner.ownergeography.city               | city            | abc                      | 0    4    1    1                |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 1  | $.owner.ownergeography.country            | country         | abc                      | 0    4    1    2                |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 1  | $.owner.ownername.firstname               | firstname       | abc                      | 0    4    2    1                |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 1  | $.owner.ownername.lastname                | lastname        | def                      | 0    4    2    2                |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 1  | $.owner.clientApiKey                      | clientApiKey    | xxxxx                    | 0    4    3                     |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 1  | $.campaignType                            | campaignType    | Mobile push              | 0    5                          |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[0].correlationIds[0].campaignId[0]      | 0               | 1                        | 0    1    1    1    1    1      |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[0].correlationIds[0].campaignId[1]      | 1               | 2                        | 0    1    1    1    1    2      |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[0].correlationIds[0].campaignId[2]      | 2               | 3                        | 0    1    1    1    1    3      |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[0].correlationIds[0].correlationId[0].a | a               | b                        | 0    1    1    1    2    1    1 |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[0].correlationIds[0].correlationId[1].c | c               | d                        | 0    1    1    1    2    2    1 |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[0].correlationIds[0].correlationId[2].e | e               | f                        | 0    1    1    1    2    3    1 |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[0].variantId                            | variantId       | 1278915                  | 0    1    2                     |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[0].utmCampaign                          | utmCampaign     |                          | 0    1    3                     |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[0].ua.os.major                          | ua.os.major     | 8                        | 0    1    4                     |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[1].correlationIds[0].campaignId[0]      | 0               | 1                        | 0    2    1    1    1    1      |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[1].correlationIds[0].campaignId[1]      | 1               | 2                        | 0    2    1    1    1    2      |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[1].correlationIds[0].campaignId[2]      | 2               | 3                        | 0    2    1    1    1    3      |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[1].correlationIds[0].correlationId[0].a | a               | b                        | 0    2    1    1    2    1    1 |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[1].correlationIds[0].correlationId[1].c | c               | d                        | 0    2    1    1    2    2    1 |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[1].correlationIds[0].correlationId[2].e | e               | f                        | 0    2    1    1    2    3    1 |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[1].variantId                            | variantId       | 1278915                  | 0    2    2                     |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[1].utmCampaign                          | utmCampaign     |                          | 0    2    3                     |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 2  | $[1].ua.os.major                          | ua.os.major     | 8                        | 0    2    4                     |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 3  | $.correlationId                           | correlationId   | ls7XmuuiThWzktUeewqgWg   | 0    1                          |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 3  | $.eventCreateTime                         | eventCreateTime | 2020-05-12T12:40:20.786Z | 0    2                          |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 3  | $.time                                    | time            | 1589287220786            | 0    3                          |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 3  | $.modifiedBy.clientApiKey                 | clientApiKey    | xxx                      | 0    4    2                     |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    | 3  | $.campaignType                            | campaignType    | Mobile push              | 0    5                          |
    +----+-------------------------------------------+-----------------+--------------------------+---------------------------------+
    

    要するに:

    • 再帰CTEを使用してこれを実行します。
    • クエリはフラグメントをテストします([value] OPENJSONから )有効なJSONであるため。
    • フラグメントが有効な場合、これはますます深くなります。
    • SortString 最終的な並べ替え順序を取得するために必要です。
    • CAST() およびCOLLATE データ型の不一致を回避するのに役立ちます。再帰的CTEは、これには非常に注意が必要です...

    ヒント:より大きなJSONを扱う場合は、OPTION (MAXRECURSION 0)を設定する必要があるかもしれません。 クエリの最後に。

    お楽しみください:-)

    XMLに似たもの

    こちら 未知のXMLの読み方についても同様の答えです。




    1. 休日の計算:Oracleの指定された日付範囲クエリ内の土曜日と日曜日の数

    2. mysqlからPDOへの移行

    3. XMLAgg/XMLElementの使用中にバッファが小さすぎるエラー

    4. 壁を壊せ!データのサイロ化を解除する方法