Read Nested Json through sql query

Viewed 43

Currently I have this piece of code

DECLARE @json NVARCHAR(MAX) 
SET @json = 
N'[
   {
     "objOrg": {
       "EmpIds": [
         {
           "Id": 101
         },
         {
           "Id": 102
         },
         {
           "Id": 103
         }
       ]
     }
   }
 ]'

How can I return EmpId values pivoted such as

Id1 Id2 Id3
101 102 103
2 Answers

OPENJSON without a schema will return the array index. Then pass the inner object to OPENJSON again to parse it out, and pivot the final result using PIVOT or MAX(CASE

DECLARE @json nvarchar(max) = 
N'[
   {
     "objOrg": {
       "EmpIds": [
         {
           "Id": 101
         },
         {
           "Id": 102
         },
         {
           "Id": 103
         }
       ]
     }
   }
 ]';
SELECT MAX(CASE WHEN arr.[key] = 0 THEN ID END) AS Id1,
       MAX(CASE WHEN arr.[key] = 1 THEN ID END) AS Id2,
       MAX(CASE WHEN arr.[key] = 2 THEN ID END) AS Id3
FROM OPENJSON(@json, '$[0].objOrg.EmpIds') arr
CROSS APPLY OPENJSON (arr.value) 
  WITH (
    Id int
  ) AS j;
-- alternatively

SELECT p.*
FROM (
    SELECT arr.[key] + 1 AS [key], j.Id
    FROM OPENJSON(@json, '$[0].objOrg.EmpIds') arr
    CROSS APPLY OPENJSON (arr.value) 
      WITH (
        Id int
      ) AS j
) j
PIVOT (
    MAX(j.Id) FOR j.[key] IN
      ([1], [2], [3])
) p;

db<>fiddle

You can use OPENJSON() along with ROW_NUMBER() window function such as

DECLARE 
    @json   AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);
        
SET @json = 
N'[
   {
     "objOrg": {
       "EmpIds": [
         {
           "Id": 101
         },
         {
           "Id": 102
         },
         {
           "Id": 103
         }
       ]
     }
   }
 ]';
 
 SELECT j.*, ROW_NUMBER() OVER (ORDER BY j.Id) AS rn
   INTO t_json
     FROM OPENJSON(@json)
              WITH (
                    JS NVARCHAR(MAX) '$.objOrg.EmpIds' AS JSON 
                  ) AS j0
    CROSS APPLY OPENJSON (j0.JS) 
                WITH (
                      Id   INT '$.Id' 
                    ) AS j; 
                    
SET @query = CONCAT('SELECT',
              STUFF(
                   (SELECT CONCAT(', MAX(CASE WHEN rn=' , CAST(rn AS VARCHAR) , ' THEN Id END) AS Id', CAST(rn AS VARCHAR))
                      FROM t_json
                     ORDER BY rn 
                       FOR XML PATH(''), type).value('.', 'NVARCHAR(MAX)'),
                   1,1,''
                  ),' FROM t_json');

EXECUTE(@query)  

Demo

Related