I have a table with two columns: [ID] and [Content] (with ISJSON constraint, so every row must have valid JSON in [Content] column).
These JSONs have an array field, which consists of objects with some specific ID (and many more fields) .
{
"departments": [ { "id": 1, "fieldA": "somevalue" },
{ "id": 2, "fieldA": "somevalue" }]
}
I'd like to perform a select query, which returns all rows with some particular id in the object from departments field.
I managed to create a script that uses a cursor fetching departments field from [Content] column into #content variable and then:
SELECT * FROM OPENJSON(#content) WITH(id int) WHERE id IN (1, 2, 3, 9)
But it returns only departmentid and I need the whole row.
Preferably it should look like that (but code below unfortunately does not work):
SELECT * FROM ITEM I WHERE EXISTS
(SELECT * FROM OPENJSON(I.CONTENT) WITH(id int) WHERE id IN (1, 2, 3, 9))
If I understood you correctly, this could get you what you need:
declare #someId varchar(10) = '1'
declare #json nvarchar(1000) = N'{ "departments": [ { "id": 1, "fieldA": "somevalue" }, { "id": 1, "fieldA": "test" }, { "id": 2, "fieldA": "somevalue" }] }'
select ids.[key], ids.[value] id_val, depts.value content
from openjson(#json, '$.departments') as depts cross apply OPENJSON(depts.value) as ids
where ids.[key] = 'id' and ids.value = #someId
I have added another element to the departments array, with the same Id = 1 just for testing the results.
EDIT:
select ids.[key], ids.[value] id_val, depts.value content
from ITEMS i cross apply openjson(i.Content, '$.departments') as depts cross apply OPENJSON(depts.value) as ids
where ids.[key] = 'id' and ids.value = #id
Related
I have a column in SQL table which has a string value denoting a JSON array. I need to concatenate the array for comparison. There are multiple rows of this data and will be using a CURSOR to iterate through a set of values because no example of using using OPENJSON on a column is available
there are solutions for iterating the array in a property ('$.list') of a JSON but nothing which talks about a direct array.
from:
ID
Value
1
[{"id": 1, "val":"j"}, {"id": 2,"val":"o"}, {"id": 3, "val":"h"}, {"id": 4, "val":"h";}, {"id": 5, "val":"n"}]
2
[{"id": 1, "val":"d"}, {"id": 2,"val":"o"}, {"id": 3, "val":"e"}]
Result:
ID
Result
1
john
2
doe
and then proceed with my other iteration logic on the Result table
If you correct the example JSON by switching the " and ' characters around you could get your desired results by way of string_agg() and openjson()...
declare #Table table (
ID int,
[Value] nvarchar(max)
);
insert #Table (ID, [Value]) values
(1, N'[{"id": 1, "val":"j"}, {"id": 2,"val":"o"}, {"id": 3, "val":"h"}, {"id": 4, "val":"h"}, {"id": 5, "val":"n"}]'),
(2, N'[{"id": 1, "val":"d"}, {"id": 2,"val":"o"}, {"id": 3, "val":"e"}]');
select ID, string_agg(J.[val], N'') as [Result]
from #Table
cross apply openjson([Value]) with (
[val] nvarchar(50)
) J
group by ID;
ID
Result
1
johhn
2
doe
I am new to SQL server I am trying to get two column values in the same row as a dictionary
Example
Table having columns Key,Value
So the dictionary/json should be
Key:Value
Any help on this would be great.
Thank you.
Consider the following example data...
create table dbo.Example (
ID int,
[Key] varchar(10),
Value varchar(10)
);
insert dbo.Example (ID, [Key], Value)
values
(1, 'Foo', 'Bar'),
(2, 'Baz', 'Chaz');
If you perform the following query on it:
select ID, [Key], Value
from dbo.Example
for json path;
You'll get the result where the object keys are the column names from the table:
[
{
"ID": 1,
"Key": "Foo",
"Value": "Bar"
},
{
"ID": 2,
"Key": "Baz",
"Value": "Chaz"
}
]
It sounds like you're wanting to pivot those using a query like the following:
select ID, [Foo], [Baz]
from (
select ID, [Key], Value
from dbo.Example
) src
pivot (max(Value) for [Key] in ([Foo], [Baz])) p
for json path;
Which yields the following result instead:
[
{
"ID": 1,
"Foo": "Bar"
},
{
"ID": 2,
"Baz": "Chaz"
}
]
The downside here is that you either (a) have to know all possible values of Key ahead of time so that they can be encoded in the statement, or (b) you have to write dynamic SQL statements that include the current set of values of Key.
I have a JSON like this to process in SQL
{"RowIndex":[1,2], "Data":["a","b"]}
and i want to extract the data to show that as a table like this
RowIndex Data
1 a
2 b
I understand that i have to use OPENJSON, JSON_QUERY or JSON_VALUE but i cannot find a way to get what I want that not implies to write a query with many join like
select C1.value as RowIndex,
C2.value as Data,
From (select [key], value from OPENJSON(JSON_QUERY(#jsonstring, '$.RowIndex'))) C1
inner join (select [key], value from OPENJSON(JSON_QUERY(#jsonstring, '$.Data'))) C2 on C1.[key] = C2.[key]
Because if the arrays in the JSON grow the query will be unmaintenable and slow
One method, using a "couple" of OPENJSON clauses:
DECLARE #JSON nvarchar(MAX) = N'{"RowIndex":[1,2], "Data":["a","b"]}';
SELECT RI.[value] AS RowIndex,
D.[value] AS Data
FROM OPENJSON(#JSON)
WITH (RowIndex nvarchar(MAX) AS JSON,
Data nvarchar(MAX) AS JSON) J
CROSS APPLY OPENJSON(RowIndex) RI
CROSS APPLY OPENJSON(Data) D
WHERE RI.[key] = D.[key];
To elaborate on my comments though, it seems like you should be fixing the JSON design and have something like this:
[
{
"RowIndex": "1",
"Data": "a",
"Number": "1"
},
{
"RowIndex": "2",
"Data": "b",
"Number": "3"
}
]
Which can be far more easily queried:
DECLARE #JSON nvarchar(MAX) = N'[
{
"RowIndex": "1",
"Data": "a",
"Number": "1"
},
{
"RowIndex": "2",
"Data": "b",
"Number": "3"
}
]';
SELECT *
FROM OPENJSON(#JSON)
WITH (RowIndex int,
Data char(1),
Number int) OJ;
i have 10 rows and 3 columns,
out of 3 columns, 2 columns have data in JSON format
I am trying to merge the data of all rows in one single column which has the json data and that is valid,
like if row 1 has a json, it should join the json and the column name and then next row and so on
Have been able to do so my data is repeated like this
[ {
"role":"poweruser",
"account":"active",
"Name" : "Rose"
},
{
"role":"Admin",
"account":"inactive",
"Name" : "Rose"
}]
output i am trying is like this
[{
"name":"Rose" {
"role":"poweruser",
"account":"active"
},
{
"role":"Admin",
"account":"inactive"
}
}]
and my table structure is like this
select role,account,(another case statement) as name
from table1 inner join table2 on table1.id = table2.id
but i want that the JSON should not repeat the name, one name and other two as nested output
Literally have no clue what i should be doing, suggestion
Microsof SQL Server has some integrated support for handling JSON, you can check out some of the documentation here and here.
Working with the "table structure" query and the little example data you provided I get this:
-- create sample data
declare #user table
(
userid int,
username nvarchar(20)
);
insert into #user (userid, username) values
(1, 'Rose');
declare #userrole table
(
userid int,
rolename nvarchar(20),
rolestatus nvarchar(20)
);
insert into #userrole (userid, rolename, rolestatus) values
(1, 'poweruser', 'active'),
(1, 'admin', 'inactive');
A very basic query where SQL Server does all the work:
select u.username as 'Name',
roles.rolename as 'Role',
roles.rolestatus as 'Account'
from #user u
join #userrole Roles
on Roles.userid = u.userid
for json auto; -- specify that we want JSON output with AUTOmatic structure
This gives:
[{"Name":"Rose","roles":[{"Role":"poweruser","Account":"active"},{"Role":"admin","Account":"inactive"}]}]
Which can be formatted as:
[
{
"Name":"Rose",
"Roles":
[
{
"Role":"poweruser",
"Account":"active"
},
{
"Role":"admin",
"Account":"inactive"
}
]
}
]
Please expand your question (with more example data) if this is not what you are after.
Let's say that I have multiple rows in a table with an nvarchar column that contains JSON data. Each row would have some simple JSON object, like { "key": "value" }. What is the best way to compose all of these objects into a single JSON object as an array, for a group of rows, such as:
{
"data": [
{ "key": "value" },
{ "key": "value" },
{ "key": "value" }
]
}
There could be any number of groups, and any number of rows per group. Each object could be different.
Currently, my approach would be to use FOR XML PATH to concatenate them into a single string, but this is prone to odd text (e.g.
) getting in there which makes it less than a resilient approach. It seems possible that I could use JSON_MODIFY but I'm not sure how I would use it in a way that accommodates unknown rows per group.
Creating arrays of JSON data in SQL is not exactly straightforward. Take the following table as an example:
CREATE TABLE #test (id INT, jsonCol NVARCHAR(MAX))
INSERT INTO #test
(
id
,jsonCol
)
VALUES
(
1
,N'{ "make": "ford" }'
),
(
1
,N'{ "make": "mazda" }'
)
,
(
2
,N'{ "color": "black" }'
)
You can use the following query to create a single JSON object with the array as you posted in your question:
SELECT DISTINCT [data] =
JSON_QUERY( '[' + STUFF(
(SELECT ',' + jsonCol FROM #test FOR XML PATH (''))
, 1, 1, '')
+ ']')
FROM #test
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
The output would look like this:
{
"data":[
{ "make": "ford" },
{ "make": "mazda" },
{ "color": "black" }
]
}
You can also correlate the id columns in the main and subqueries to get the json grouped by id.
Here's an example:
SELECT DISTINCT id
, [json] = (SELECT DISTINCT [data] =
JSON_QUERY( '[' + STUFF(
(SELECT ',' + jsonCol FROM #test t3 WHERE t3.id = t2.id FOR XML PATH (''))
, 1, 1, '')
+ ']')
FROM #test t2
WHERE t2.id = t1.id
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)
FROM #test t1
Output would be:
id json
1 {"data":[{ "make": "ford" },{ "make": "mazda" }]}
2 {"data":[{ "color": "black" }]}