Postgres + Sequelize: How to read function result? - json

I have a function payment_summary() as below:
CREATE OR REPLACE FUNCTION payment_summary()
RETURNS SETOF PAYMENT_SUMMARY_TYPE
LANGUAGE plpgsql
AS $$
DECLARE
payment_sum payment_summary_type%ROWTYPE;
BEGIN
FOR payment_sum IN SELECT
pay.application_no,
project.title,
pay.payment_rec,
customer.cust_name,
project.estimated_cost,
(project.estimated_cost - pay.payment_rec) AS outstanding_amt
FROM project
INNER JOIN customer
ON project.customer_cust_id = customer.cust_id
INNER JOIN
(SELECT
project.application_no,
sum(payment.amount) AS payment_rec
FROM payment
INNER JOIN project
ON payment.project_id = project.project_id
WHERE payment.drcr_flg = 'Cr'
GROUP BY project.application_no) AS pay
ON pay.application_no = project.application_no
LOOP
RETURN NEXT payment_sum;
END LOOP;
END;
$$;
PAYMENT_SUMMARY_TYPE is defined as:
CREATE TYPE PAYMENT_SUMMARY_TYPE AS
(
application_no VARCHAR(150),
title VARCHAR(500),
payment_rec INTEGER,
customer_name VARCHAR(500),
estimated_cost INTEGER,
outstanding_amt INTEGER
);
Using below code to execute the function and get results:
sequelize.query('SELECT payment_summary()').then(function(data) {
res.json(data);
});
Getting below as response:
[
[
{
"payment_summary": "(716,\"C1\",100000,\"C1 - city\",0,-100000)"
},
{
"payment_summary": "(716,\"C2\",100000,\"C2 - city\",0,-100000)"
}
],
{
"command": "SELECT",
"rowCount": 2,
"oid": null,
"rows": [
{
"payment_summary": "(716,\"C1\",100000,\"C1 - city\",0,-100000)"
},
{
"payment_summary": "(716,\"C2\",100000,\"C2 - city\",0,-100000)"
}
],
"fields": [
{
"name": "payment_summary",
"tableID": 0,
"columnID": 0,
"dataTypeID": 17453,
"dataTypeSize": -1,
"dataTypeModifier": -1,
"format": "text"
}
],
"_parsers": [
null
],
"rowAsArray": false
}
]
I need the response in below format:
[
{
application_no: 716,
title: "C1",
payment_rec : 100000,
customer_name : "C1 - city"
estimated_cost : 0
outstanding_amt : -100000
},
{
application_no: 717,
title: "C2",
payment_rec : 100000,
customer_name : "C2 - city"
estimated_cost : 0
outstanding_amt : -100000
}
]
How can i read / convert the response in required format ?

Related

query json document SQL Server

I'm trying read data from a json document stored on azure data lake storage from an Azure SQL database using the below query. I tried a couple of ways and nothing seems to bring the data back. I tried using this '$.data[0].AccID' in OPENJSON for instance and brings back only the first record from multiple arrays but, not sure how to bring back all the data.
json:
[
{
"data": [
{
"AccID": 1234,
"CustID": 456,
"Total": 1234.1234,
"OrderDate": "2022-12-01"
},
{
"AccID": 5678,
"CustID": 890,
"Total": 5678.5678,
"OrderDate": "2022-12-01"
}
],
"count": 2
},
{
"data": [
{
"AccID": 1234,
"CustID": 456,
"Total": 100.0,
"OrderDate": "2021-12-01"
},
{
"AccID": 5678,
"CustID": 890,
"Total": 200.0,
"OrderDate": "2021-12-01"
},
{
"AccID": 8900,
"CustID": 235,
"Total": 300.0,
"OrderDate": "2021-12-01"
}
],
"count": 3
}
]
Query:
SELECT *
FROM OPENROWSET (
BULK 'blobpath/file.json',
DATA_SOURCE = 'adls',
SINGLE_CLOB
) AS [data]
CROSS APPLY OPENJSON (X.BulkColumn, '$.value')
WITH (
AccID int,
CustID int,
Total float,
OrderDate date)
I created storage account and uploaded Json file into container,
reference image.
input .json:
[
{
"data": [
{
"AccID": 1234,
"CustID": 456,
"Total": 1234.1234,
"OrderDate": "2022-12-01"
},
{
"AccID": 5678,
"CustID": 890,
"Total": 5678.5678,
"OrderDate": "2022-12-01"
}
],
"count": 2
},
{
"data": [
{
"AccID": 1234,
"CustID": 456,
"Total": 100.0,
"OrderDate": "2021-12-01"
},
{
"AccID": 5678,
"CustID": 890,
"Total": 200.0,
"OrderDate": "2021-12-01"
},
{
"AccID": 8900,
"CustID": 235,
"Total": 300.0,
"OrderDate": "2021-12-01"
}
],
"count": 3
}
]
I generated sas token and created masterkey and data source. I created a table in sql with following columns
Create table data1( ACCID varchar(100),
CustID varchar(100),
Total float(100),
OrderDate date,
count int )
Insert data into that table using below code:
INSERT INTO data1
SELECT ACCID,CustID,Total,OrderDate,count FROM OPENROWSET(
BULK 'jsonfile path',
DATA_SOURCE = 'your data source'
SINGLE_CLOB
) AS DataFile
cross apply openjson(BulkColumn)
WITH (
AccID varchar(100) '$.data[0].AccID',
CustID varchar(100) '$.data[0].CustID',
Total float '$.data[0].Total',
OrderDate date '$.data[0].OrderDate',
count int '$.count'
)
INSERT INTO data1
SELECT ACCID,CustID,Total,OrderDate,count FROM OPENROWSET(
BULK 'jsonfile path',
DATA_SOURCE = 'your data source'
SINGLE_CLOB
) AS DataFile
cross apply openjson(BulkColumn)
WITH (
AccID varchar(100) '$.data[1].AccID',
CustID varchar(100) '$.data[1].CustID',
Total float '$.data[1].Total',
OrderDate date '$.data[1].OrderDate',
count int '$.count'
)
INSERT INTO data1
SELECT ACCID,CustID,Total,OrderDate,count FROM OPENROWSET(
BULK 'jsonfile path',
DATA_SOURCE = 'your data source'
SINGLE_CLOB
) AS DataFile
cross apply openjson(BulkColumn)
WITH (
AccID varchar(100) '$.data[2].AccID',
CustID varchar(100) '$.data[2].CustID',
Total float '$.data[2].Total',
OrderDate date '$.data[2].OrderDate',
count int '$.count'
)
Data is inserted successfully.
I retrieved the data of table I got as below
I deleted the Null values row using below code
Image for reference:
delete from data1 where ACCID is Null
I retrieved the data of table order by count according to the json using below code
select * from data1 order by count
Output:
In this way I retrieve all the data from Json document.

How to join nested JSON indices to multiple rows in SQL by primary key

I am trying to update several rows in SQL with JSON.
I'd like to match a primary key on a table row to an index nested in an array of JS objects.
Sample data:
let json = [{
"header": object_data,
"items": [{
"id": {
"i": 0,
"name": "item_id"
},
"meta": {
"data": object_data,
"text": "some_text"
}
}, {
"id": {
"i": 4,
"name": "item_id4"
},
"meta": {
"data": object_data,
"text": "some_text"
}
}, {
"id": {
"i": 17,
"name": "item_id17"
},
"meta": {
"data": object_data,
"text": "some_text"
}}]
}]
Sample table:
i | json | item_id
---+---------------------------+---------
0 | entire_object_at_index_0 | item_id
4 | entire_object_at_index_4 | item_id4
17 | entire_object_at_index_17 | item_id17
entire_object_at_index, meaning appending the item data to the header to create a new object for each row.
"header" "some_data",
"items": [{
"id": {
"i": 0,
"name": "item_id1"
},
"meta": {
"data": "some_data",
"text": "some_text"
}
}]
SQL:
update someTable set
json = json_value(#jsons, '$') -- not sure how to join on index here
item_id = json_value(#jsons, '$.items[?].id.name' -- not sure how to select by index here
where [i] = json_query(#jsons, '$.items.id.i')
The requirement to repeat the other properties complicates this a bit, because we need to build a new object explicitly. Even so it's not too hard:
update someTable
set
[json] = (
select (
select
"header" = json_query(#json, '$.header'),
"items" = json_query(N'[' + items.item + N']')
for json path, without_array_wrapper
)
),
item_id = items.item_id
from openjson(#json, '$.items') with (
item nvarchar(max) '$' as json,
item_id varchar(50) '$.id.name',
i int '$.id.i'
) items
join someTable on [someTable].i = items.i
Here I'm assuming the #json has already been unwrapped from its array, as your query seems to assume. If it's not, substitute $.[0] for $ in the outer query.
Update:
It's an attempt to improve my answer (I missed the header part of the JSON content in the original answer). Of course, the #JeroenMostert's answer is an excellent solution, so this is just another possible approach. Note, that if header part of JSON content is scalar value, you should use JSON_VALUE().
Table and JSON:
-- Table
CREATE TABLE #Data (
i int,
[json] nvarchar(max),
item_id nvarchar(100)
)
INSERT INTO #Data
(i, [json], [item_id])
VALUES
(0 , N'entire_object_at_index_0', N'item_id'),
(4 , N'entire_object_at_index_4', N'item_id4'),
(17, N'entire_object_at_index_17', N'item_id17')
-- JSON
DECLARE #json nvarchar(max) = N'[{
"header": {"key": "some_data"},
"items": [{
"id": {
"i": 0,
"name": "item_id"
},
"meta": {
"data": "some_data",
"text": "some_text"
}
}, {
"id": {
"i": 4,
"name": "item_id4"
},
"meta": {
"data": "some_data",
"text": "some_text"
}
}, {
"id": {
"i": 17,
"name": "item_id17"
},
"meta": {
"data": "some_data",
"text": "some_text"
}}]
}]'
Statement:
UPDATE #Data
SET #Data.Json = j.Json
FROM #Data
CROSS APPLY (
SELECT
JSON_QUERY(#json, '$[0].header') AS header,
JSON_QUERY(j.[value], '$') AS items
FROM OPENJSON(#json, '$[0].items') j
WHERE JSON_VALUE(j.[value], '$.id.i') = #Data.[i]
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
) j ([Json])
Original answer:
One possible approach is to use OPENJSON and appropriate join:
Table and JSON:
-- Table
CREATE TABLE #Data (
i int,
[json] nvarchar(max),
item_id nvarchar(100)
)
INSERT INTO #Data
(i, [json], [item_id])
VALUES
(0 , N'entire_object_at_index_0', N'item_id'),
(4 , N'entire_object_at_index_4', N'item_id4'),
(17, N'entire_object_at_index_17', N'item_id17')
-- JSON
DECLARE #json nvarchar(max) = N'[{
"header": "some_data",
"items": [{
"id": {
"i": 0,
"name": "item_id"
},
"meta": {
"data": "some_data",
"text": "some_text"
}
}, {
"id": {
"i": 4,
"name": "item_id4"
},
"meta": {
"data": "some_data",
"text": "some_text"
}
}, {
"id": {
"i": 17,
"name": "item_id17"
},
"meta": {
"data": "some_data",
"text": "some_text"
}}]
}]'
Statement:
UPDATE #Data
SET [json] = j.[value]
FROM #Data
LEFT JOIN (
SELECT
[value],
JSON_VALUE([value], '$.id.i') AS [i]
FROM OPENJSON(#json, '$[0].items')
) j ON (#Data.[i] = j.[i])

Convert table result to a form of JSON

I am trying to form json from a table result set :
create table testmalc(
appid int identity(1,1),
propertyid1 int ,
propertyid1val varchar(10) ,
propertyid2 int,
propertyid2val varchar(10) ,
)
insert into testmalc values(456,'t1',789,'t2')
insert into testmalc values(900,'t3',902,'t4')
need below desired JSON result :
{
"data": {
"record": [{
"id": appid,
"customFields": [{
"customfieldid": propertyid1 ,
"customfieldvalue": propertyid1val
},
{
"customfieldid": propertyid2 ,
"customfieldvalue": propertyid2val
}
]
},
{
"id": appid,
"customFields": [{
"customfieldid": propertyid1 ,
"customfieldvalue": propertyid1val
},
{
"customfieldid": propertyid2 ,
"customfieldvalue": propertyid2val
}
]
}
]
}
}
I am trying to use stuff but was not getting the desired result. Now trying with UnPivot.
If you cannot upgrade to SQL-Server 2016 for JSON support you should try to solve this in any application / programming language you know of.
Just for fun, I provide an approach, which works, but is more a hack than a solution:
Your test data:
DECLARE #testmalc table (
appid int identity(1,1),
propertyid1 int ,
propertyid1val varchar(10) ,
propertyid2 int,
propertyid2val varchar(10)
);
insert into #testmalc values(456,'t1',789,'t2')
,(900,'t3',902,'t4');
--create a XML, which is the most similar structure and read it as a NVARCHAR string
DECLARE #intermediateXML NVARCHAR(MAX)=
(
SELECT t.appid AS id
,(
SELECT t2.propertyid1 AS [prop1/#customfieldid]
,t2.propertyid1val AS [prop1/#customfieldvalue]
,t2.propertyid2 AS [prop2/#customfieldid]
,t2.propertyid2val AS [prop2/#customfieldvalue]
FROM #testmalc t2
WHERE t2.appid=t.appid
FOR XML PATH('customFields'),TYPE
) AS [*]
FROM #testmalc t
GROUP BY t.appid
FOR XML PATH('row')
);
--Now a bunch of replacements
SET #intermediateXML=REPLACE(REPLACE(REPLACE(REPLACE(#intermediateXML,'=',':'),'/>','}'),'<prop1 ','{'),'<prop2 ','{');
SET #intermediateXML=REPLACE(REPLACE(REPLACE(REPLACE(#intermediateXML,'<customFields>','"customFields":['),'</customFields>',']'),'customfieldid','"customfieldid"'),'customfieldvalue',',"customfieldvalue"');
SET #intermediateXML=REPLACE(REPLACE(#intermediateXML,'<id>','"id":'),'</id>',',');
SET #intermediateXML=REPLACE(REPLACE(REPLACE(#intermediateXML,'<row>','{'),'</row>','}'),'}{','},{');
DECLARE #json NVARCHAR(MAX)=N'{"data":{"record":[' + #intermediateXML + ']}}';
PRINT #json;
The result (formatted)
{
"data": {
"record": [
{
"id": 1,
"customFields": [
{
"customfieldid": "456",
"customfieldvalue": "t1"
},
{
"customfieldid": "789",
"customfieldvalue": "t2"
}
]
},
{
"id": 2,
"customFields": [
{
"customfieldid": "900",
"customfieldvalue": "t3"
},
{
"customfieldid": "902",
"customfieldvalue": "t4"
}
]
}
]
}
}

json_agg() with pseudo row

CREATE TABLE content
(
code INTEGER NOT NULL
, nameid TEXT NOT NULL
)
INSERT INTO content(code, nameid) VALUES
( 0, 'Support')
, ( 1, 'Adrenaline')
, ( 2, 'Aquapark')
;
Need select all content as JSON array-object named 'content' with pseudo row with code = '' and nameid = 'All'
What i did:
1) Simple select
SELECT
json_build_object('content', (SELECT json_agg(json_build_object(
'code', s.code::TEXT
, 'nameid', s.nameid::TEXT
))
FROM content s
)
);
Result is
{
"content": [{
"code": "0",
"nameid": "Support"
},
{
"code": "1",
"nameid": "Adrenaline"
},
{
"code": "2",
"nameid": "Aquapark"
}
]
}
All fine, but how to add pseudo row?
2) Best i can did
SELECT
json_build_object('content', json_build_array(
json_build_object(
'code', ''
, 'nameid', 'All'::TEXT),
(SELECT json_agg(json_build_object(
'code', s.code::TEXT
, 'nameid', s.nameid::TEXT
))
FROM content s
))
);
Result is
{
"content": [{
"code": "",
"nameid": "All"
},
[{
"code": "0",
"nameid": "Support"
},
{
"code": "1",
"nameid": "Adrenaline"
},
{
"code": "2",
"nameid": "Aquapark"
}
]
]
}
And we have array in array, as in sql as in json, but i can not understand how to combine json_agg with pseudo row.
Use to_json() and union all:
select jsonb_build_object('content', json_agg(to_json))
from (
select to_json(c)
from (select '' as code, 'All' as nameid) c
union all
select to_json(c)
from content c
) s
Output:
{
"content": [
{
"code": "",
"nameid": "All"
},
{
"code": 0,
"nameid": "Support"
},
{
"code": 1,
"nameid": "Adrenaline"
},
{
"code": 2,
"nameid": "Aquapark"
}
]
}
The version with an alias in the derived table:
select jsonb_build_object('content', json_agg(codes))
from (
select to_json(c) as codes
from (select '' as code, 'All' as nameid) c
union all
select to_json(c)
from content c
) s

reading nested json data from Flex table in vertica

I have this json file.
[
{
"Modified": "2016-09-0",
"Id": 16,
"Name": "ABC",
"Filters": [],
"ScoreComponents":[
{
"Id": 86,
"Name": "Politeness",
"Bins": [],
"Ranges": [
{
"ComponentId": 86,
"LastUser": "CDE\\John.Doe"
},
{
"ComponentId": 86,
"LastUser": "CDE\\John.Doe"
}
],
"Filters": []
},
{
"Id": 87,
"Name": "Empathy",
"Bins": [],
"Ranges": [
{
"ComponentId": 87,
"LastUser": "CDE\\John.Doe"
}
],
"Filters": [
{
"ComponentID": -30356,
"BucketID": 81
}
]
},
{
"Id": 88,
"Name": "Ownership",
"Bins": [],
"Ranges": [
{
"ComponentId": 88,
"User": "CDE\\John.Doe"
}
],
"Filters": []
}]
}
]
I have loaded this file In Vertica flex table
CREATE FLEX TABLE flex_test();
copy events_stg.flex_test from LOCAL 'C:/test2.json' PARSER fjsonparser (flatten_maps= true, flatten_arrays = false)
I want to read all data from ScoreComponents including nested arrays.
I tried query this query
select "Id" as scoreid,mapitems("ScoreComponents") OVER(PARTITION BY
"Id") from flex_test
getting output like:
I just dont understand those small squares in output. I am a student and this vertica DB and Flex tables are new me.
I have tried with flatten_arrays = true but its giving me empty result set.
You're getting squares because the values field contains a binary VMap.
This should do it:
create flex table so_flex();
create table so_score_components(
id int,
name varchar(100)
);
create table so_ranges(
parent_id int,
component_id int,
last_user varchar(100)
);
create table so_filters(
parent_id int,
component_id int,
bucket_id int
);
copy so_flex from local 'E:\Demos\so.json'
parser fjsonparser(start_point='ScoreComponents',
flatten_maps = false, flatten_arrays = false);
insert into so_score_components(id, name)
select id::int, name::varchar from so_flex;
insert into so_ranges(parent_id, component_id, last_user)
select id::int, values['ComponentId']::int, values['LastUser']::varchar
from (
select id, mapitems(ranges) over (partition by id)
from so_flex
) t;
insert into so_filters(parent_id, component_id, bucket_id)
select id::int, values['ComponentID']::int, values['BucketID']::int
from (
select id, mapitems(filters) over (partition by id)
from so_flex
) t;