Postgresql array to json - arrays

I have a table like:
id
time_serie
value
1
2020-09-25 00:00:00
100
1
2020-09-25 00:10:00
200
1
2020-09-25 00:20:00
300
1
2020-09-25 00:30:00
400
I want a JSON output as:
{
"ID": 1,
"time_serie": [
{
"position": 1,
"inQuantity": 100
},
{
"position": 2,
"inQuantity": 200
},
{
"position": 3,
"inQuantity": 300
},
{
"position": 4,
"inQuantity": 400
}
...
]
}
Thanks

You can use a mix of JSON functions along with ROW_NUMBER() window function in order to generate positions such as
SELECT *
FROM
(
SELECT JSON_BUILD_OBJECT('ID', id,
'time_serie',
JSON_AGG(
JSON_BUILD_OBJECT('position',id,'inQuantity',value)
)
)
FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY time) AS rn FROM t) AS t
GROUP BY id
) AS j
Demo

Related

snowflake, how to combine all result into json when doing a group by

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" } } ]

SQL Server 2019 - Build JSON with spread operator

I'm required to supply a json object like this:
[
{
id: '59E59BC82852A1A5881C082D5FFCAC10',
user: {
...users[1],
last_message: "16-06-2022",
topic: "Shipment"
},
unread: 2,
},
{
id: '521A754B2BD028B13950CB08CDA49075',
user: {
...users[2],
last_message: "15-06-2022",
topic: "Settings"
},
unread: 0,
}
]
it is not difficult for me to build a json like this:
(with this fiddle https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=bf62626de20d3ca7191aa9c1ef0cd39b)
[
{
"id": "59E59BC82852A1A5881C082D5FFCAC10",
"user": {
"id": 1,
"last_message": "16-06-2022",
"topic": "Shipment"
},
"unread": 2
},
{
"id": "521A754B2BD028B13950CB08CDA49075",
"user": {
"id": 2,
"last_message": "15-06-2022",
"topic": "Settings"
},
"unread": 1
},
{
"id": "898BB874D0CBBB1EFBBE56D2626DC847",
"user": {
"id": 3,
"last_message": "18-06-2022",
"topic": "Account"
},
"unread": 1
}
]
but I have no idea how to put the ...users[1], instead of "id": 1 into user node:
is there a way?
This is not actually valid JSON, but you can create it yourself using STRING_AGG and CONCAT
SELECT
'[' + STRING_AGG(u.spread, ',') + ']'
FROM (
SELECT
spread = CONCAT(
'{id:''',
u.userId,
''',user:{...users[',
ROW_NUMBER() OVER (ORDER BY u.id),
'],last_message: "',
t.created_at,
'",topic:"',
t.topic,
'"},unread:',
(SELECT COUNT(*) FROM #tickets t3 WHERE t3.userId = u.userId AND t3.read_at IS NULL),
'}'
)
FROM #Users u
CROSS APPLY (
SELECT top 1
t.ticketId,
t.created_at,
t.topic
FROM #Tickets t
WHERE t.userId = u.userId
ORDER BY
t.created_at DESC
) t
) u
Note that you may need to escape values, but I don't know how this not-JSON works so couldn't say.
db<>fiddle

SQL Server : SELECT JSON Column in this JSON Structure

I would like to know will it possible to select data from below JSON structure?
[
{
"A": 6,
"Status": 1
},
{
"A": 3,
"Status": 0
},
{
"A": 6,
"Status": 1
},
{
"A": 7,
"Status": 0
}
]
According this link, there is Property before the array/object.
"EmployeeInfo": {
"FirstName":"Jignesh",
"LastName":"Trivedi",
"Code":"CCEEDD",
"Addresses": [
{ "Address":"Test 0", "City":"Gandhinagar", "State":"Gujarat"},
{ "Address":"Test 1", "City":"Gandhinagar", "State":"Gujarat"}
]
}
For example, (getting sample from above link), we see the query is started with property EmployeeInfo so that make query possible to get data in this query.
SELECT JSON_VALUE(#JSONData, '$.EmployeeInfo.FirstName')
So I just can't figure out how could this be achieve from the structure provide above, anyone could point me to some sample code that will be helpful. Thanks.
You have two options to parse this JSON array:
Using OPENJSON() with explicit schema once - to get the content of each item
Using OPENJSON() twice - to get the index and the content of each item
JSON:
DECLARE #json varchar(max) = '
[
{
"A": 6,
"Status": 1
},
{
"A": 3,
"Status": 0
},
{
"A": 6,
"Status": 1
},
{
"A": 7,
"Status": 0
}
]'
Using OPENJSON() with explicit schema once:
SELECT A, Status
FROM OPENJSON(#json) WITH (
A int,
Status int
)
Result:
A Status
6 1
3 0
6 1
7 0
Using OPENJSON() twice:
SELECT
j1.[key] AS Index,
j2.A, j2.Status
FROM OPENJSON(#json) j1
CROSS APPLY OPENJSON(j1.[value]) WITH (
A int,
Status int
) j2
Result:
Index A Status
0 6 1
1 3 0
2 6 1
3 7 0
Of course, you can always access an array item by index:
SELECT
JSON_QUERY(#json, '$[0]') AS Item,
JSON_VALUE(#json, '$[0].A') AS A,
JSON_VALUE(#json, '$[0].Status') AS Status
Result:
Item A Status
{"A": 6, "Status": 1} 6 1
Something like this
declare #json nvarchar(max) =N'
[
{
"A": 6,
"Status": 1
},
{
"A": 3,
"Status": 0
},
{
"A": 6,
"Status": 1
},
{
"A": 7,
"Status": 0
}
]'
select * from openjson(#json) with (A int,
Status int);
Output
A Status
6 1
3 0
6 1
7 0

PostgreSQL json and array processing

I need to output json out from the query.
Input data:
Documents:
==========
id | name | team
------------------
1 | doc1 | {"authors": [1, 2, 3], "editors": [3, 4, 5]}
Persons:
========
id | name |
--------------
1 | Person1 |
2 | Person2 |
3 | Person3 |
4 | Person4 |
5 | Person5 |
Query:
select d.id, d.name,
(select jsonb_build_object(composed)
from
(
select teamGrp.key,
(
select json_build_array(persAgg) from
(
select
(
select jsonb_agg(pers) from
(
select person.id, person.name
from
persons
where (persList.value)::int=person.id
) pers
)
from
json_array_elements_text(teamGrp.value::json) persList
) persAgg
)
from
jsonb_each_text(d.team) teamGrp
) teamed
) as teams
from
documents d;
and i expect the following output:
{"id": 1, "name": "doc1", "teams":
{"authors": [{"id": 1, "name": "Person1"}, {"id": 2, "name": "Person2"}, {"id": 3, "name": "Person3"}],
"editors": [{"id": 3, "name": "Person3"}, {"id": 5, "name": "Person5"}, {"id": 5, "name": "Person5"}]}
But received an error:
ERROR: more than one row returned by a subquery used as an expression
Where is the problem and how to fix it?
PostgreSQL 9.5
I think the following (super complicated query) should to it:
SELECT
json_build_object(
'id',id,
'name',name,
'teams',(
SELECT json_object_agg(team_name,
(SELECT
json_agg(json_build_object('id',value,'name',Persons.name))
FROM json_array_elements(team_members)
INNER JOIN Persons ON (value#>>'{}')::integer=Persons.id
)
)
FROM json_each(team) t(team_name,team_members)
)
)
FROM Documents;
I am using subqueries where I run json aggregates.

how to return row if value find in array in postgres

{
actName: null,
applicable: {
applicable: [ 5, 4, 1 ]
},
status: 1,
id: 2
}
{
actName: null,
applicable: {
applicable: [ 3, 2 ]
},
status: 1,
id: 1
}
Is that possible to find value in array, like if i search integer value 2 in applicable array return one row with id 1.
with t(j) as (values
('{
"actName": null,
"applicable": {
"applicable": [ 5, 4, 1 ]
},
"status": 1,
"id": 2
}'::jsonb),
('{
"actName": null,
"applicable": {
"applicable": [ 3, 2 ]
},
"status": 1,
"id": 1
}')
)
select j ->> 'id' as id
from t
where exists (
select 1
from jsonb_array_elements_text(j -> 'applicable' -> 'applicable') s(i)
where i = '2'
)
;
id
----
1
With JSONB's #> you can query for any element by following the structure of your document, for example:
WITH data(d) AS (VALUES
('{
"actName": null,
"applicable": {
"applicable": [ 5, 4, 1 ]
},
"status": 1,
"id": 2
}'::JSONB),
('{
"actName": null,
"applicable": {
"applicable": [ 3, 2 ]
},
"status": 1,
"id": 1
}')
)
SELECT d ->> 'id' AS id
FROM data
WHERE d #> '{"applicable":{"applicable":[1]}}';
Assumption here is that you have jsonb with array of json docs in your database, query may be the following:
WITH test_data AS (
SELECT '[{
"actName": "null",
"applicable": {
"applicable": [5,4,1]
},
"status":1,
"id":2
},
{
"actName": "null",
"applicable": {
"applicable": [3,2]
},
"status": 1,
"id": 1
}]'::JSONB AS jsonb_value
)
SELECT
jsonb_doc->>'id' AS id,
jsonb_doc->'applicable' #>'{applicable}' AS appl_array_result
FROM
test_data td,
jsonb_array_elements(td.jsonb_value) AS jsonb_doc
WHERE (jsonb_doc->'applicable' #>'{applicable}') #> '2'::JSONB;
Output:
id | appl_array_result
----+-------------------
1 | [3, 2]
(1 row)

Resources