简体   繁体   中英

Parse nested JSON in SQL Server

I have stored data in sql server as Json format, which as give below. I would like to retrieve it as normal string value. I have tried JSON_VALUE but json may or may not have more than one child, so it should retrieve all the values.

Input

TableA

   ID Education
   -------------------------------------------------------------------------------------
    1  {"Education": {"Record":[{"SLSubject":"MICRO ECONOMICS","Score":"77","Grade":"A"}]}}
    2  {"Education": {"Record":[{"SLSubject":"Math","Score":"89","Grade":"A"},{"SLSubject":"eng","Score":"88","Grade":"B"},{"SLSubject":"tam","Score":"33","Grade":"C"}]}}
    3  {"Education":{"Record":[{"SLSubject":"subject 1","Score":"87","Grade":"A"},{"SLSubject":"subject 2","Score":"67","Grade":"B"},{"SLSubject":"subject 3","Score":"45","Grade":"C"},{"SLSubject":"subject 4","Score":"87","Grade":"D"}]}}

Expected Output

ID Education
-------------------------------------------------------------------------------------
1  MICRO ECONOMICS - 77 - A
2  Math - 88 - B \n end - 88 - B \n Tam - 33 - C
3  subject 1 - 87- A \n subject 2 - 67- B \n subject 3 - 45- C \n subject 1 - 87- D \n

Query (which is working for one child)

SELECT ID, JSON_VALUE(Education,'$.Education.Record[0].SLSubject')
FROM TableA

Actual Result

ID Education
-------------------------------------------------------------------------------------
1  MICRO ECONOMICS - 77 - A
2  Math - 88 - B
3  subject 1 - 87- A

Sample JSON:

{"Education":{"Record":[{"SLSubject":"subject 1","Score":"87","Grade":"A"},{"SLSubject":"subject 2","Score":"67","Grade":"B"},{"SLSubject":"subject 3","Score":"45","Grade":"C"},{"SLSubject":"subject 4","Score":"87","Grade":"D"}]}}

You need to use OPENJSON and treat your data as a dataset, JSON_VALUE is for returning a scalar value. This'll likely be what you really want:

SELECT YT.ID,
       OJ.SLSubject,
       OJ.Score,
       OJ.Grade
FROM (VALUES(1,N'[{"SLSubject":"MICRO ECONOMICS","Score":"77","Grade":"A"}]'),
            (2,N'[{"SLSubject":"Math","Score":"89","Grade":"A"},{"SLSubject":"eng","Score":"88","Grade":"B"},{"SLSubject":"tam","Score":"33","Grade":"C"}]'),
            (3,N'[{"SLSubject":"subject 1","Score":"87","Grade":"A"},{"SLSubject":"subject 2","Score":"67","Grade":"B"},{"SLSubject":"subject 3","Score":"45","Grade":"C"},{"SLSubject":"subject 4","Score":"87","Grade":"D"}]'))YT(ID,Education) 
     CROSS APPLY OPENJSON(YT.Education) 
                 WITH (SLSubject varchar(20),
                       Score int,
                       Grade char(1)) OJ;

Seems the OP wants this?

SELECT YT.ID,
       STRING_AGG(CONCAT(OJ.SLSubject, ' - ', OJ.Score, ' - ', OJ.Grade),' \n ') WITHIN GROUP (ORDER BY OJ.SLSubject) AS Education
FROM (VALUES(1,N'[{"SLSubject":"MICRO ECONOMICS","Score":"77","Grade":"A"}]'),
            (2,N'[{"SLSubject":"Math","Score":"89","Grade":"A"},{"SLSubject":"eng","Score":"88","Grade":"B"},{"SLSubject":"tam","Score":"33","Grade":"C"}]'),
            (3,N'[{"SLSubject":"subject 1","Score":"87","Grade":"A"},{"SLSubject":"subject 2","Score":"67","Grade":"B"},{"SLSubject":"subject 3","Score":"45","Grade":"C"},{"SLSubject":"subject 4","Score":"87","Grade":"D"}]'))YT(ID,Education) 
     CROSS APPLY OPENJSON(YT.Education) 
                 WITH (SLSubject varchar(20),
                       Score int,
                       Grade char(1)) OJ
GROUP BY YT.ID;

DB<>Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM