I have JSON array value column in database:
[
{
"id": 1,
"name": "One"
},
{
"id": 2,
"name": "Two"
}
]
I want to add a new key-value into each object. Expected result is:
[
{
"id": 1,
"name": "One",
"active": "1"
},
{
"id": 2,
"name": "Two",
"active": "1"
}
]
By using JSON_MODIFY I can add a new key-value into one of the object as following:
UPDATE MyTable
SET JsonValueColumn=JSON_MODIFY(JsonValueColumn,'$[1].active','1')
WHERE Id = 'id'
But I need to add a new key-value into all objects in JSON array. I have an option to iterate in json objects, add new key-value, combine them again and update JsonValueColumn with the new value.
But I am looking if there is a simpler way to achieve this. Something like:
UPDATE MyTable
SET JsonValueColumn=JSON_MODIFY(JsonValueColumn,'$[*].active','1')
WHERE Id = 'id'
This is the simplest way I found so far:
UPDATE MyTable
SET JsonValueColumn= '[' + (
SELECT
STRING_AGG(JSON_MODIFY([value],'$.active', '1'), ',') WITHIN GROUP (ORDER BY CAST([key] AS int))
FROM
OPENJSON(JsonValueColumn)
) + ']'
From: https://stackoverflow.com/a/62648430/2794280
You can use OPENJSON to break out the JSON objects, then CROSS APPLY the new value, then rebuild with FOR JSON:
UPDATE MyTable
SET JsonValueColumn =
(SELECT *
FROM OPENJSON(#json) WITH (id int, name varchar(100))
CROSS APPLY (VALUES(1)) v(active)
FOR JSON PATH);
Related
I have a table with values like this
table-1
id
value-1
value-2
id-1
test
{"id": "value","other": "this"}
id-2
foo-1
{"id": "value","other": "this"}
id-2
foo-2
{"id": "value1","other": "this"}
I want to be able to group by column id and produce results like
id
json_value
id-1
[{"value-1": "foo-1","value-2": {"id": "ran","other": "this"}}]
id-2
[{"value-1":"foo-1","value-2":{"id":"value1","other":"this"}},{"value-1":"foo-2","value-2":{"id":"value","other":"this"}}]
Which is to collect all columns for the grouped id and convert each row to json using column name as key and column value as the actual value.
You can use object_construct and array_agg within group to do this:
create or replace temp table T1 as
select
COLUMN1::string as id,
COLUMN2::string as "value-1",
COLUMN3::string as "value-2"
from (values
('id-1','test','{"id": "value","other": "this"}'),
('id-2','foo-1','{"id": "value","other": "this"}'),
('id-2','foo-2','{"id": "value1","other": "this"}')
);
select id
,array_agg(object_construct('value-1', "value-1", 'value-2', parse_json("value-2")))
within group (order by ID) as JSON_VALUE
from T1
group by ID
;
ID
JSON_VALUE
id-1
[ { "value-1": "test", "value-2": { "id": "value", "other": "this" } } ]
id-2
[ { "value-1": "foo-1", "value-2": { "id": "value", "other": "this" } }, { "value-1": "foo-2", "value-2": { "id": "value1", "other": "this" } } ]
I have a json in bigQuery
{
"actors": {
"stooges": [
{
"id": 1,
"name": "Larry"
},
{
"id": 2,
"name": "Curly"
},
{
"id": 3,
"name": "Moe"
}
]
}
}
How do I extract each of the .names in bigQuery.
["Larry", "Curly", "Moe"]
Here are some handy bigQuery compatible statements(based on above json).
-- Declaring a bigQuery variable
DECLARE json_data JSON DEFAULT (SELECT PARSE_JSON('{ "actors": {"stooges": [{"id": 1,"name": "Larry"},{"id": 2,"name": "Curly"},{"id": 3,"name": "Moe"}]}}'));
-- Select statement. But this is no good for my use case since I don't want to specify element index ([0]) as the array size is dynamic
SELECT JSON_EXTRACT(json_data, '$.actors.stooges[0].name');
You may try and consider below approach using JSON_EXTRACT_ARRAY() then unnest it and then use JSON_EXTRACT_SCALAR() to extract the values. You may refer to this documentation for more details in BigQuery JSON functions.
select ARRAY(
SELECT JSON_EXTRACT_SCALAR(json_array, '$.name') from UNNEST(JSON_EXTRACT_ARRAY(json_data,"$.actors.stooges"))json_array
)extracted_names
Output:
From this JSON File (just an example) I need to reach this final result
{
"Id": "101",
"name": "C01",
"testparameters": {
"room": [
{
"Floor": "First_Floor",
"Rooms": ["Room1", "Room2", "Room3"]
},
{
"Floor": "Second_Floor",
"Rooms": ["Room1", "Room2", "Room3"]
}
],
"area": [
{
"Name": "Area1",
"Subarea": ["Subarea1", "Subarea2", "Subarea3"]
},
{
"Name": "Area2",
"Subarea": ["Subarea4", "Subarea5"]
}
],
"requirements": [{
"condition": "",
"type": "type1",
"field1": "",
"field2": "aaaaa",
"operator": "",
"value2": ""
},
{
"condition": "AND",
"type": "type2",
"field1": "",
"field2": "numPersons",
"operator": ">",
"value2": "20"
},
{
"condition": "OR",
"type": "type2",
"field1": "",
"field2": "specification",
"operator": "=",
"value2": "wifi"
}
]
}
}
'
In one register I need to have all the information that is requested.
This is the first time that I need to parse a JSON file. After asking (a lot) I manage to reach the expected result by doing this:
Parsing JSON Example
However, I had to open the JSON file several times, and process each section apart. I'm wondering, how can I improve the code by reducing the number of times that I need to use the OPENJSON function, and in particular, how to rewrite the code snippet that handle the requirements section.
I must say, your desired result looks pretty de-normalized, you may want to rethink it.
Be that as it may, you can combine these quite easily, by using nested subqueries
SELECT
ID = JSON_VALUE(j.json, '$.Id'),
name = JSON_VALUE(j.json, '$.name'),
area = (
SELECT STRING_AGG(concat(d.a , ':', b.value),' - ')
from openjson(j.json, '$.testparameters.area')
with
(
a nvarchar(250) '$.Name',
s nvarchar(max) '$.Subarea' as json
) as d
cross apply openjson(d.s) as b
),
room = (
SELECT STRING_AGG(concat(c.f, ':', d.value), ' - ')
from openjson(j.json, '$.testparameters.room')
with(
f nvarchar(50) '$.Floor',
r nvarchar(Max) '$.Rooms' as json
) as c
cross apply openjson(c.r) as d
),
requirements = (
SELECT IIF(
SUBSTRING(requirements,1,3) = 'AND' or SUBSTRING(requirements,1,3) = 'OR',
SUBSTRING(requirements,5,LEN(requirements)),
requirements
)
from
(
select
STRING_AGG(CONCAT_WS(' ',
a.condition,
a.field2,
operator,
IIF (ISNUMERIC(a.value2) = 1,
a.value2,
CONCAT('''',a.value2,'''')
)
),
' ') as requirements
from openjson(j.json, '$.testparameters.requirements' )
with
(
condition nvarchar(255) '$.condition',
type nvarchar(255) '$.type',
field2 nvarchar(255) '$.field2',
operator nvarchar(255) '$.operator',
value2 nvarchar(255) '$.value2'
) a
where a.type = 'type2'
) a
)
FROM (VALUES(#json)) AS j(json) -- or you can reference a table
I have the following JSON array data set that needs to be parsed into 2 table rows:
[
{ "eid": "ABCDGD",
"name": "Carol E",
"email": "carole#gmail.com",
"role": "Recruiter"
},
{ "eid": "HDHDK",
"name": "Mark H",
"email": "markh#gmail.com",
"role": "Manager"
}
]
I need the code below to return both sets of employee information but it only returns one. How do I achieve this?
select p.* from
(SELECT j2.[key] as _keys, j2.Value as _vals
FROM OPENJSON(#c) j1
CROSS APPLY OPENJSON(j1.Value) j2
) as pds
PIVOT
(
max(pds._vals)
FOR pds._keys IN([eid], [name], [email], [role])
) AS p
SQLfiddle - http://sqlfiddle.com/#!18/9eecb/54970
No need to pivot, just specify your json columns and will give your desired results.
SELECT *
FROM OPENJSON(#c) WITH (
eid varchar(200) '$.eid',
name varchar(200) '$.name',
email varchar(200) '$.email',
role varchar(200) '$.role'
) j1
JSON is already maintaining a table kind structure in it and can be directly converted into table by using OPENJSON.
As the syntax of OPENJSON on MSDN website.
OPENJSON( jsonExpression [ , path ] ) [ <with_clause> ]
<with_clause> ::= WITH ( { colName type [ column_path ] [ AS JSON ] } [ ,...n ] )
Here just need to pass your column name as maintained in JSON and will convert your JSON into SQL Table.
You may find more details on this link.
For your above query you may try this.
DECLARE #json NVARCHAR(MAX)
SET #json =
N'[
{ "eid": "ABCDGD",
"name": "Carol E",
"email": "carole#gmail.com",
"role": "Recruiter"
},
{ "eid": "HDHDK",
"name": "Mark H",
"email": "markh#gmail.com",
"role": "Manager"
}
]'
SELECT *
FROM OPENJSON(#json)
WITH (
eid nvarchar(50) '$.eid',
name nvarchar(50) '$.name',
email nvarchar(50) '$.email',
role nvarchar(50) '$.role',
)
I have a column saved json data in my table:
declare #json nvarchar(max)
set #json = N'
{
"Companies": [
{
"CompanyId": "A",
"Employee": null
},
{
"CompanyId": "B",
"Employee": [
{
"EmployeePictureId": null,
"Name": "Employee1"
},
{
"EmployeePictureId": "PictureId2",
"Name": "Employee2"
}
]
},
{
"CompanyId": "C",
"Employee": [
{
"EmployeePictureId": null,
"Name": "Employee3"
},
{
"EmployeePictureId": null,
"Name": "Employee4"
}
]
}
]
}
'
Is it posible to get the result like:
{
"EmployeePictureIds": ["PictureId2"]
}
using the Json_Query, Json_Value, OPENJSON...
Only get EmployeePictureId and skip empty(null) data
By the way, the count of elements in array are not sure.
In SQL Server 2017 you can use the following query:
select json_query(QUOTENAME(STRING_AGG('"' + STRING_ESCAPE( A.EmployeePictureId , 'json')
+ '"', char(44)))) as [EmployeePictureIds]
FROM OPENJSON(#json, '$.Companies')
WITH
(
CompanyId NVARCHAR(MAX),
Employee NVARCHAR(MAX) as json
) as B
cross apply openjson (B.Employee)
with
(
EmployeePictureId VARCHAR(50),
[Name] VARCHAR(50)
) as A
where A.EmployeePictureId is not null
for json path , WITHOUT_ARRAY_WRAPPER
Results for the JSON you provided:
Results adding another non null EmployeePictureId: