1

Table columns :

id
---------
details

My table column details has json object like

"data" : [ {
   "name" : "luke",
   "dob" : "12-10-90",
   "addr" : "sample1",
 }, 
{
    "name" : "sam",
    "dob" : "12-10-88",
    "addr" : "sample2"
   }
]

I want to write a query which will give me records like below :

| id   | name|  dob      |addr       |
|:-----|:----|:--- ------|:----------|
| 1    | luke|  12-10-90 |  sample1  |
| 1    | sam |  12-10-88 |  sample2  |

I tried with

select 
    ID,
    JSON_VALUE(DETAILS, '$.data[0].name') , 
    JSON_VALUE(DETAILS, '$.data[0].dob') , 
        JSON_VALUE(DETAILS, '$.data[0].addr')
from 
    users;

RESULT WITH COUNT :

id  cnt  name       dob       addr   
--  ---  ---------  --------  -------
 1    5  luke       12-10-90  sample1
 1    5  sam        12-10-88  sample2
 2    5  awd        12-10-90  sample1
 2    5  awdawdm    12-10-88  sample2
 2    5  sevsevsev  12-10-88  sample2

EXPECTED

id  cnt  name       dob       addr   
--  ---  ---------  --------  -------
 1    2  luke       12-10-90  sample1
 1    2  sam        12-10-88  sample2
 2    3  awd        12-10-90  sample1
 2    3  awdawdm    12-10-88  sample2
 2    3  sevsevsev  12-10-88  sample2
2
  • But I've to hardcoded the index and its still not giving two rows. Commented Mar 16, 2021 at 3:56
  • @DaleK I've tried with json_value but its not looping on its own depending on number of elements in the json object and also how can I have two different rows for the same id? Commented Mar 16, 2021 at 4:00

2 Answers 2

3

To get all the objects from json array along with other columns you can use OpenJson() and Cross Apply as below:

 create table users (id int, details nvarchar(max));
 insert into users values (1,N'{
               "data":[
                       {
                        "name" : "luke",
                        "dob" : "12-10-90",
                        "addr" : "sample1"
                       },
                       {
                         "name" : "sam",
                         "dob" : "12-10-88",
                         "addr" : "sample2"
                       }
                      ]
              }');

Query:

 SELECT u.id,count(details.name)over() cnt, details.name, details.dob,details.addr,details.*
 FROM users u CROSS APPLY OPENJSON (u.details,N'$.data') 
           WITH (   
                   
                 [Name] VARCHAR(100) '$.name',
                 dob VARCHAR(10) '$.dob',
                 addr VARCHAR(100) '$.addr'
                
               
  ) AS details

Output:

id cnt name dob addr Name dob addr
1 2 luke 12-10-90 sample1 luke 12-10-90 sample1
1 2 sam 12-10-88 sample2 sam 12-10-88 sample2

db<>fiddle here

Your code is working @DLV. Please check. There were problem with data formatting.

 create table users (id int, details nvarchar(max));
 insert into users values (1,N'{"data" : 
 [ {     "name" : "luke",     "dob" : "12-10-90",     "addr" : "sample1",   },  
 {      "name" : "sam",      "dob" : "12-10-88",      "addr" : "sample2"    }  
 ]}');




 select 
     ID,
     JSON_VALUE(DETAILS, '$.data[0].name') , 
     JSON_VALUE(DETAILS, '$.data[0].dob') , 
     JSON_VALUE(DETAILS, '$.data[0].addr')
 from 
     users;

Output:

ID (No column name) (No column name) (No column name)
1 luke 12-10-90 sample1

db<>fiddle here

Sign up to request clarification or add additional context in comments.

5 Comments

Your answer is what exactly I was looking for, thank you.
A quick question : Is there any way to get a count of number of items within the data? I wanted have a where condition for more than 5 elements.
Number of rows?
Like in your example we have two records inside 'data' attribute. How can I get a count of these records?
If I add one more record with three elements in data attribute I get above response. What I am looking for is ID 1 should have count 2 where ID 2 should have count 3. Currently both saying count as 5.
2

You can loop through every record and use OPENJSON to achieve this.

DECLARE @Id int
,@details NVARCHAR(MAX)

DROP TABLE IF EXISTS #Result
CREATE TABLE #Result (Id INT, [Name] VARCHAR(100),dob VARCHAR(10),addr VARCHAR(100))

DECLARE json_cursor CURSOR FOR 
SELECT Id,details 
FROM #DetailsTable  -- Replace with your table

OPEN json_cursor  
FETCH NEXT FROM json_cursor INTO @Id,@details

WHILE @@FETCH_STATUS = 0  
BEGIN  
      
      BEGIN
      INSERT INTO #Result
        SELECT @Id AS Id,*
            FROM OPENJSON(@details,N'$.data')
            WITH (   
                  
                            [Name] VARCHAR(100) '$.name',
                            dob VARCHAR(10) '$.dob',
                            adrr VARCHAR(100) '$.addr'
               
              
             ) 
      END

      FETCH NEXT FROM json_cursor INTO @Id,@details 
END 

CLOSE json_cursor  
DEALLOCATE json_cursor 

SELECT * FROM #Result

make sure your json object is enclosed in '{}' like below

{"data" : [ {
   "name" : "luke",
   "dob" : "12-10-90",
   "addr" : "sample1",
 }, 
{
    "name" : "sam",
    "dob" : "12-10-88",
    "addr" : "sample2"
   }
]}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.