{
"product": "car",
"fuel": {
"Maruti": {
"Model": {
"LXI": [
{
"Price": "700000"
}
],
"VXI": [
{
"Price": "800000"
}
],
"ZXI": [
{
"Price": "900000"
}
]
}
}
}
}
}
i have this JSON stored in SQL table and need t fetch it from CarDetails Table
table structure is as below:
ID
JSONData(this col has JSON stored)
CreatedDate
there can be more models as well like 10 or 20 or 1000....... I need all different prices for this in SQL Server. Can anyone assist
I need this data as:
700000
800000
900000
can anyone help me out in this.
I tried cross apply but it did not helped.
Having the model names as property keys complicates things slightly, but it's still possible to extract this data with multiple cross applies of the OPENJSON() function, e.g.:
declare #demo table (
ID int,
JSONData nvarchar(max)
);
insert #demo (ID, JSONData) values (47, N'{
"product": "car",
"fuel": {
"Maruti": {
"Model": {
"LXI": [
{
"Price": "700000"
}
],
"VXI": [
{
"Price": "800000"
}
],
"ZXI": [
{
"Price": "900000"
}
]
}
}
}
}
}');
select ID, J.product, K.[key] as [Model], L.Price
from #demo
cross apply openjson(JSONData) with (
product nvarchar(50),
ModelJSON nvarchar(max) '$.fuel.Maruti.Model' as JSON
) J
cross apply openjson(J.ModelJSON) K -- default columns: [key],[value],[type]
cross apply openjson(K.[value]) with (
Price nvarchar(10)
) L;
Which yields the results:
ID
product
Model
Price
47
car
LXI
700000
47
car
VXI
800000
47
car
ZXI
900000
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" } } ]
The JSON object contains this:
"entities": {
"hashtags": [
{
"indices": [
17,
29
],
"text": "HBOMAX4ZACK"
},
{
"indices": [
38,
51
],
"text": "TheSnyderCut"
}
],
I want to select only those rows that contain 'XYZ' in ANY ONE of the entries in 'hashtags'. I know I can do this:
select record_content:text, * from tweets where record_content:entities:hashtags[0].text = 'HBOMAX4ZACK';
But as you can see, I have hard-coded 'hashtags[0]' in this case. I want to check if 'HBOMAX4ZACK' exists in any element.
Use lateral and FLATTEN to explode the json. With flatten you are exploding the json up to the level you need (in path):
select t.json,
t2.VALUE value_matching
from (select parse_json('{
"entities": {
"hashtags": [{
"indices": [
17,
29
],
"text": "HBOMAX4ZACK"
},
{
"indices": [
38,
51
],
"text": "TheSnyderCut"
}
]
}
}') as json) t,
lateral flatten(input => parse_json(t.json), path => 'entities.hashtags') t2
WHERE t2.VALUE:text = 'HBOMAX4ZACK';
You can find a tutorial to the topic here https://community.snowflake.com/s/article/How-To-Lateral-Join-Tutorial
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 am trying to update a log with JSON in SQL Server 2017. I can update a data point with json_value, which covers a few cases, but would ultimately like to join in incoming JSON.
Sample table:
key | col_1 | col_2 | col_3
----+-------------------------------+---------------|-----------------
1 | json.lines[0].data.meta.data | json.lines[0] | json.header.note
2 | json.lines[1].data.meta.data} | json.lines[1] | json.header.note
3 | json.lines[2].data.meta.data} | json.lines[2] | json.header.note
I'd like to update a single property in col_1 and update col_2 with an object as as as string.
Sample JSON:
declare #json nvarchar(max) = '[{
header: {
note: 'some note'
}, lines: [{
data {
id: {
key: 0,
name: 'item_1'
},
meta: {
data: 'item_1_data'
}
}, {...}, {...}
}]
}]'
Query:
update logTable set
col_1 = json_value(#json,'$.lines[__index__].data.meta.data'), -- what would the syntax for __index__ be?
col_2 = j.lines[key], -- pseudo code
col_3 = json_value(#json, '$'.header.note')
inner join openjson(#json) j
on json_value(#json,'$.line[?].id.key') = logTable..key -- ? denotes indices that I'd like to iterate = join over
Expected Output:
key | col_1 | col_2 | col_3
----+---------------+----------------------------|---------
1 | 'item_1_data' | 'data: { id: { key: 0...}' | '{header: { note: ...} }'
2 | 'item_2_data' | 'data: { id: { key: 1...}' | '{header: { note: ...} }'
3 | 'item_3_data' | 'data: { id: { key: 2...}' | '{header: { note: ...} }'
I'm not sure how to handle iterating over the $.line indices, but think a join would solve this if properly implemented.
How can I join to arrays of objects to update SQL rows by primary key?
Original answer:
You may try to parse your JSON using OPENJSON with explicit schema (note, that your JSON is not valid):
Table and JSON:
CREATE TABLE #Data (
[key] int,
col_1 nvarchar(100),
col_2 nvarchar(max)
)
INSERT INTO #Data
([key], [col_1], [col_2])
VALUES
(1, N'', N''),
(2, N'', N''),
(3, N'', N'')
DECLARE #json nvarchar(max) = N'[{
"lines": [
{
"data": {
"id": {
"key": 1,
"name": "item_1"
},
"meta": {
"data": "item_1_data"
}
}
},
{
"data": {
"id": {
"key": 2,
"name": "item_2"
},
"meta": {
"data": "item_2_data"
}
}
},
{
"data": {
"id": {
"key": 3,
"name": "item_3"
},
"meta": {
"data": "item_3_data"
}
}
}
]
}]'
Statement:
UPDATE #Data
SET
col_1 = j.metadata,
col_2 = j.data
FROM #Data
INNER JOIN (
SELECT *
FROM OPENJSON(#json, '$[0].lines') WITH (
[key] int '$.data.id.key',
metadata nvarchar(100) '$.data.meta.data',
data nvarchar(max) '$' AS JSON
)
) j ON #Data.[key] = j.[key]
Update:
Header is common for all rows, so use JSON_QUERY() to update the table:
Table and JSON:
CREATE TABLE #Data (
[key] int,
col_1 nvarchar(100),
col_2 nvarchar(max),
col_3 nvarchar(max)
)
INSERT INTO #Data
([key], col_1, col_2, col_3)
VALUES
(1, N'', N'', N''),
(2, N'', N'', N''),
(3, N'', N'', N'')
DECLARE #json nvarchar(max) = N'[{
"header": {
"note": "some note"
},
"lines": [
{
"data": {
"id": {
"key": 1,
"name": "item_1"
},
"meta": {
"data": "item_1_data"
}
}
},
{
"data": {
"id": {
"key": 2,
"name": "item_2"
},
"meta": {
"data": "item_2_data"
}
}
},
{
"data": {
"id": {
"key": 3,
"name": "item_3"
},
"meta": {
"data": "item_3_data"
}
}
}
]
}]'
Statement:
UPDATE #Data
SET
col_1 = j.metadata,
col_2 = j.data,
col_3 = JSON_QUERY(#json, '$[0].header')
FROM #Data
INNER JOIN (
SELECT *
FROM OPENJSON(#json, '$[0].lines') WITH (
[key] int '$.data.id.key',
metadata nvarchar(100) '$.data.meta.data',
data nvarchar(max) '$' AS JSON
)
) j ON #Data.[key] = j.[key]
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: