How to insert nested JSON into PostgreSQL - sql

CREATE TABLE Log (
"Name" TEXT,
"Age" TEXT,
"Country" TEXT,
"Numbers" TEXT
);
SELECT "Country", "Numbers"
FROM json_populate_record( null:: log,
'{
"Name": "qazwsx",
"HostName": "Age",
"Address": {
"Country": "MNB",
"Numbers": [
{
"Cell": 7418520
}
]
}
}');
SELECT * FROM Log
DEMO: The response is always null. Is there any other trick to insert nested JSON into the table?

CREATE TABLE Log (
"Name" TEXT,
"Age" TEXT,
"Country" TEXT,
"Numbers" TEXT
);
INSERT INTO Log VALUES('Oslo', '12', 'No', '12');
SELECT jsonb_pretty(
json_build_object(
'Name',
'qazwsx',
'HostName',
"Age",
'Address',
json_build_object(
'Country',
'MNB',
'Numbers',
json_build_object('Cell',7418520)
)
)::jsonb
) AS Output
FROM Log;
Output:
{
"Name": "qazwsx",
"HostName": "12",
"Address": {
"Country": "MNB",
"Numbers": {
"Cell": 7418520
}
}
}

A quick and dirty example:
SELECT
json_extract_path_text('{"Name": "qazwsx","HostName": "Age","Address": {
"Country": "MNB", "Numbers": [{"Cell":7418520}]}}'::json, 'Address', 'Country') AS "Country",
json_extract_path_text('{"Name": "qazwsx","HostName": "Age","Address": {
"Country": "MNB", "Numbers": [{"Cell":7418520}]}}'::json, 'Address', 'Numbers') AS "Numbers";
Country | Numbers
---------+--------------------
"MNB" | [{"Cell":7418520}]
A little better version using the JSON path language from her JSON functions9.16.2. The SQL/JSON Path Language:
SELECT
t[0] AS "Country",
t[1] AS "Numbers"
FROM
jsonb_path_query_array('{"Name": "qazwsx","HostName": "Age","Address": {
"Country": "MNB", "Numbers": [{"Cell":7418520}]}}'::jsonb, '$.Address.*') AS t;
Country | Numbers
---------+---------------------
"MNB" | [{"Cell": 7418520}]
Though the above does depend on the ordering in the Address object staying the same.

CREATE TABLE Log (
"Name" TEXT,
"Age" TEXT,
"Country" TEXT,
"Numbers" TEXT
);
DECLARE
jsonstr text;
jsonobj jsonb;
jsonstr = '{
"Name": "qazwsx",
"HostName": "Age",
"Address": {
"Country": "MNB",
"Numbers": [
{
"Cell": 7418520
}
]
}
}';
SELECT jsonstr::json INTO jsonobj;
INSERT INTO
Log
SELECT
jsonobj->'Name',
jsonobj->'HostName'
((jsonobj->'Address')::json)->'Country',
(((jsonobj->'Address')::json)#>'{Numbers,0}')::json->'Cell';
SELECT * FROM Log

Related

Update one key value in JSON using Presto

I have a JSON column (_col0) like below and wanted to update only the 'name' part of json to new value.
{
"id":"1234",
"name":"Demo 1",
"attributes":[
{
"id": "1122",
"name": "affiliate",
"type": "number"
}
],
"behaviors": [
{
"id": "246685",
"name": "Email Send",
"scheduleOption": null,
"defaultTimeFilterEnabled": true,
"schema": []
}
]
}
I wanted to only change value of the outer "name" parameter from 'Demo 1' to 'Demo 2'. The SQL I tried does change the name parameter but makes the rest all to null.
select transform_values(cast(json_parse(_col0) as MAP(varchar, json)) , (k, v) -> if(k='name','Demo 2')) from table1
if has overload with 3 parameters, the 3rd being value for false case, use it to return the current value (you will need to transform either you varchar literal to json or json value to varchar):
-- sample data
WITH dataset (json_str) AS (
VALUES ('{
"id":"1234",
"name":"Demo 1",
"attributes":[
{
"id": "1122",
"name": "affiliate",
"type": "number"
}
],
"behaviors": [
{
"id": "246685",
"name": "Email Send",
"scheduleOption": null,
"defaultTimeFilterEnabled": true,
"schema": []
}
]
}')
)
-- query
select transform_values(
cast(json_parse(json_str) as MAP(varchar, json)),
(k, v)->if(k = 'name', cast('Demo 2' as json), v)
)
from dataset
Output:
_col0
{behaviors=[{"id":"246685","name":"Email Send","scheduleOption":null,"defaultTimeFilterEnabled":true,"schema":[]}], name="Demo 2", attributes=[{"id":"1122","name":"affiliate","type":"number"}], id="1234"}

Select data from Json array MS SQL Server

I have to select data from Json like this:
[
{
"id": 10100,
"externalId": "100000035",
"name": "Test1",
"companyId": 10099,
"phone": "0738003811",
"email": "test#Test.com",
"mainAddress": {
"county": "UK",
"province": "test",
"zipCode": "01234",
"city": "test",
"street": "test",
"gln": "44,37489331;26,21941193",
"country": {
"iso2": "UK",
"iso3": "UK"
}
},
"active": false,
"main": true,
"stores": [
"Test"
],
"attributes": [
{
"attributeId": 1059,
"attributeName": "CH6 name",
"attributeExternalId": null,
"attributeValueId": 74292,
"attributeValueType": "MONO_LINGUAL",
"attributeValueEid": null,
"attributePlainValue": "Unknown"
},
{
"attributeId": 1061,
"attributeName": "BD",
"attributeExternalId": null,
"attributeValueId": 81720,
"attributeValueType": "MONO_LINGUAL",
"attributeValueEid": null,
"attributePlainValue": "Not assigned"
}
],
"daysSinceLastOrder": null
},
{
"id": 62606,
"externalId": "VL_LC_000190",
"name": "Test",
"companyId": 17793,
"phone": "44333424",
"email": "test#email.com",
"mainAddress": {
"firmName": "test",
"county": "test",
"province": "test",
"zipCode": "247555",
"city": "test",
"street": "test",
"gln": "44.8773851;23.9223518",
"country": {
"iso2": "RO",
"iso3": "ROU"
},
"phone": "07547063789"
},
"active": true,
"main": false,
"stores": [
"Valcea"
],
"attributes": [
{
"attributeId": 1042,
"attributeName": "Type of location",
"attributeExternalId": "TYPE_OF_DIVISION",
"attributeValueId": 34506,
"attributeValueType": "MONO_LINGUAL",
"attributeValueEid": "Small OTC (<40mp)",
"attributePlainValue": "Small OTC (<40mp)"
},
{
"attributeId": 17,
"attributeName": "Limit for payment",
"attributeExternalId": "LIMIT_FOR_PAYMENT_IN_DAYS",
"attributeValueId": 59120,
"attributeValueType": "NUMBER",
"attributeValueEid": null,
"attributePlainValue": "28"
}
],
"daysSinceLastOrder": 147
}
]
I know how to select data from simple json object using "FROM OPENJSON",
but now I have to select a
AttributeValueId, AttributeId and AttributeName, attributePlainValue and CompanyId for each Attribute. So I dont know how to select data from attributes array and then how to join to this CompanyId which is one level up.
Maybe someone knows how write this query.
As mentioned by #lptr in the comments:
You need to pass the result of one OPENJSON to another, using CROSS APPLY. You can select a whole JSON object or array as a property, by using the syntax AS JSON
select
t1.companyid,
t2.*
from openjson(#j)
with (
companyId int,
attributes nvarchar(max) as json
) as t1
cross apply openjson(t1.attributes)
with
(
attributeId int,
attributeName nvarchar(100),
attributeValueId nvarchar(100),
attributePlainValue nvarchar(100)
) as t2;
db<>fiddle
For example, you can use code like this.
f1.metaData->"$.identity.customerID" = '.$customerID.'

Generate nested JSON from stored procedure

I have sample data in a SQL Server table in the following format
CREATE TABLE #tempA
(
HomeId int IDENTITY PRIMARY KEY,
City nvarchar(20),
State nchar(2),
Email VARCHAR(50)
);
INSERT INTO #tempA (City, State, Email)
VALUES ('Cleveland', 'OH', 'sd#aol.com')
INSERT INTO #tempA (City, State, Email)
VALUES ('Malibu', 'CA', 'sd#aol.com')
INSERT INTO #tempA (City, State, Email)
VALUES ('Atlanta', 'GA', 'ploll#aol.com')
SELECT * FROM #tempA
I need a JSON output returned by a stored procedure in the following format, I am trying to group it by email field, I tried using JSON AUTO but not able to achieve in the following format ? Any tips?
[
{
"Email": "sd#aol.com",
"Tasks": [
{
"City": "Cleveland",
"State": "OH"
},
{
"City": "Malibu",
"State": "CA"
}
]
},
{
"Email": "ploll#aol.com",
"Tasks": [
{
"City": "Atlanta",
"State": "GA"
}
]
}
]
One method would be to use a subquery for the State and Email values and group on the email column in the outer query:
SELECT A.Email,
(SELECT B.City,
B.State
FROM #tempA B
WHERE A.Email = B.Email
ORDER BY B.City ASC
FOR JSON AUTO) AS Tasks
FROM #tempA A
GROUP BY A.Email
ORDER BY A.Email DESC
FOR JSON AUTO;
Which gives:
[
{
"Email": "sd#aol.com",
"Tasks": [
{
"City": "Cleveland",
"State": "OH"
},
{
"City": "Malibu",
"State": "CA"
}
]
},
{
"Email": "ploll#aol.com",
"Tasks": [
{
"City": "Atlanta",
"State": "GA"
}
]
}
]

How to get the inner elements of JsonB column in Postgres

I have a Json like this in my JsonB column:
{
"emails": [
{
"email": {
"id": "a8399412-165e-4601-824f-a55f631ad471",
"value": "test#gmail.com"
}
},
{
"email": {
"id": "fa09d9a7-a36a-42a4-8627-66b7554ce82e",
"value": "test1#gmail.com"
}
}
],
"Address": [
{
"address": {
"id": "a8399412-165e-4601-824f-a55f631ad471",
"addressLine1": "Line1"
}
},
{
"address": {
"id": "fa09d9a7-a36a-42a4-8627-66b7554ce82e",
"addressLine2": "Line2"
}
}
],
"lastName": {
"id": "bc10a5a9-04ff-4a00-b167-ac3232e5cb89",
"value": "LastName"
},
"firstName": {
"id": "4ccdd400-2586-4a7f-9379-aff4d1f5d9d6",
"value": "FirstName"
}
}
and so on. My requirement to get list of elements as key and value pairs with limit, I did a research tried different functions of postgres and I wrote the below query :
select response.* from my_table t, jsonb_each_text(jsonb_column) as response;
If I do like this I'm getting only the root elements like emails, firstName and lastName, but I want inner elements as well along with their values like below :
Key | value
------- ---------
"email" : {"id": "a8399412-165e-4601-824f-a55f631ad471","value": "test#gmail.com"}
"email" : {"id": "fa09d9a7-a36a-42a4-8627-66b7554ce82e","value": "test1#gmail.com"}
"lastName" : {"id": "bc10a5a9-04ff-4a00-b167-ac3232e5cb89","value": "LastName"}
"firstName" : {"id": "4ccdd400-2586-4a7f-9379-aff4d1f5d9d6","value": "FirstName"}
"address" : {"id": "a8399412-165e-4601-824f-a55f631ad471", "addressLine1": "Line1"}
"address" : {"id": "a8399412-165e-4601-824f-a55f631ad471", "addressLine2": "Line2"}
You can use jsonb_array_elements() function, and combine queries by UNION ALL
SELECT 'email' AS key, je.* ->> 'email' AS value
FROM my_table
CROSS JOIN jsonb_array_elements(jsonb_column->'emails') AS je
UNION ALL
SELECT 'address', ja.* ->> 'address'
FROM my_table
CROSS JOIN jsonb_array_elements(jsonb_column->'Address') AS ja
UNION ALL
SELECT 'lastName', (jsonb_column->'lastName')::text
FROM my_table
UNION ALL
SELECT 'firstName', (jsonb_column->'firstName' )::text
FROM my_table
Demo

Azure SQL - How to remove attribute text from output

I am trying to remove the "attribute" from the output of Azure SQL for json path.
Consider the below test data:
create table test (country varchar(50), city varchar(50));
insert into test values ('US', 'New York');
insert into test values ('US', 'Las Vegas');
insert into test values ('France', 'Paris');
insert into test values ('Canada', 'Toranto');
insert into test values ('Canada', 'Vancouver');
The below SQL when run gives the output shown:
select DISTINCT country, (select city
from test b
where b.country=a.country
for json path
) as city
from test a
for json path;
Output:
[
{
"country": "Canada",
"city": [
{
"city": "Toranto"
},
{
"city": "Vancouver"
}
]
},
{
"country": "France",
"city": [
{
"city": "Paris"
}
]
},
{
"country": "US",
"city": [
{
"city": "New York"
},
{
"city": "Las Vegas"
}
]
}
]
However, I would like the output to be of the below form i.e. city attribute removed from the output and the values as an array
[
{
"country": "Canada",
"city": [
"Toranto"
, "Vancouver"
]
},
{
"country": "France",
"city": [
"Paris"
]
},
{
"country": "US",
"city": [
"New York"
,"Las Vegas"
]
}
]
Thanks
Check if the following works for you:
select DISTINCT country as country,json_query((select CONCAT('[','"', STRING_AGG(city, '","'), '"',']')
from test b
where b.country=a.country
)) as city
from test a
for json path
Example here.