1

I'm trying to pull some information from a JSON array stored in an SQL Server database. I can see I need to use OPENJSON, and I've found numerous examples of how to use it, but the rub is all of the examples demonstrate declaring a single JSON array as a variable and using OPENJSON to open it (e.g. How to read field name with space in Json using OPENJSON in SQL Server 2016). I'd like to know how to actually build this into a database query.

Example structure of database table:

Table: HELP_INFO

UID ID JSON
1 45745 JSON varchar - example below
2 45745 JSON varchar - example below
3 82567 JSON varchar - example below

Example structure of the JSON

Example 1
    {"source":"XYZ",
     "source_info":{
         "type":"need_help",
         "help_info":{     
                "questions":50, 
                "details":[{"floatv":0.42,"name":"Tom"},{"floatv":1.08,"name":"Dick"},{"floatv":1.2,"name":"Harry"}]}}}

Example 2
    {"source":"XYZ",
     "source_info":{
         "type":"need_help",
         "help_info":{     
                "questions":12, 
                "details":[{"floatv":2.0,"name":"Donald"},{"floatv":0.4,"name":"Mickey"}]}}}

For each row in the table I need to open the "details" list in the JSON and extract all of the "name" values. The items in the details list always have the same keys, but the number of items in the list varies.

How would I write a query to do this, getting the source JSON values and their ID from rows on the HELP_INFO table?

Desired output:

UID NAMES
45745 Tom Dick Harry
45745 Donald Mickey
82567 Other names

Thanks

1 Answer 1

2

You need an OPENJSON() call with the appropriate path to access the nested $.source_info.help_info.details JSON array and STRING_AGG() to aggregate the names:

Sample data:

SELECT *
INTO Data
FROM (VALUES
   (1, 45745, '{"source":"XYZ",
     "source_info":{
         "type":"need_help",
         "help_info":{     
                "questions":50, 
                "details":[{"floatv":0.42,"name":"Tom"},{"floatv":1.08,"name":"Dick"},{"floatv":1.2,"name":"Harry"}]}}}')
) v (UID, ID, JSON)

Statement:

SELECT 
   ID, 
   NAMES = (
      SELECT STRING_AGG(JSON_VALUE([value], '$.name'), ' ') 
             WITHIN GROUP (ORDER BY CONVERT(int, [key]))
      FROM OPENJSON(JSON, '$.source_info.help_info.details')
   )
FROM Data
3
  • Unbelievable! Great solution and ridiculously fast. Thank you so much, if would have taken me a long time to get there.
    – Steve
    Commented Apr 6, 2022 at 15:58
  • 1
    That CONVERT(int, [key]) annoys me so much, I wish it was already an int and I wish it had a unique and ordering constraint, preventing the need for a Sort in the execution plan. Oh well, we can dream.... Commented Apr 6, 2022 at 16:07
  • @Charlieface, I agree and I'm waiting for the new SQL Server 2022 JSON features ...
    – Zhorov
    Commented Apr 6, 2022 at 16:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.