Make Column value as key using JSON function in Postgres - sql

I'm using Postgres database and have a table as below
Table Name: Test
id firstname lastname
1 Sam Crews
2 John Dave
I'm trying to get result set back in below JSON format but with no luck
Expected:
[{"1": {"firstname": "Sam", "lastname": "Crews"}},
{"2": {"firstname": "John", "lastname": "Dave"}}
]
I tried using row_to_json, json_build_object functions but the output is bit different (as below).
Actual:
[{"id": "1", "firstname": "Sam", "lastname": "Crews"},
{"id": "2", "firstname": "John", "lastname": "Dave"}
]
Any pointers on how to achieve expected result would be greatly appreciated.
Thank you!

row_to_json() will always use all column names to create the keys in the JSON document. If you only want two columns, you need to explicitly specify them.
You also want a nested JSON object, so you need to nest the methods to create one:
select json_agg(json_build_object(
id,
json_build_object('firstname', firstname, 'lastname', lastname))
)
from the_table;
Klin made me realize that with Postgres 9.6 you can simplify the creation of the firstname/lastname object:
select json_agg(json_build_object(id, to_jsonb(the_table) - 'id'))
from the_table;

with my_table(id, firstname, lastname) as (
values
(1, 'Sam', 'Crews'),
(2, 'John', 'Dave')
)
select jsonb_agg(obj)
from my_table,
jsonb_build_object(id, to_jsonb(my_table)- 'id') obj
jsonb_agg
------------------------------------------------------------------------------------------------------
[{"1": {"lastname": "Crews", "firstname": "Sam"}}, {"2": {"lastname": "Dave", "firstname": "John"}}]
(1 row)

Related

ILIKE query inside arrays of objects in jsonb column

I have a jsonb data column made up of various objects. Here is an example.
{"LicensePlates": {"Type": "LicensePlateList", "Value": ["XXXXX"]}, "SubscriptionInfo": {"Type": "SubscriptionInfoList", "Value": [{"id": "1", "lastname": "rossi", "firstname": "paola"}, {"id": "2", "lastname": "Scicolone", "firstname": "Paolo"}]}}
Now I'm searching a specific info in SubscriptionInfo key like this:
SELECT * FROM column WHERE (data -> 'SubscriptionInfo') -> 'Value' #> '[{"firstname": "Paolo"}]';
It works fine, but I would also like to search for "partial" information, eg. searching for the string "pa" (using ILIKE or anything else similar) should return the entire record. it's possible?
You have two options (demo)
convert data to lower case
select *
from
test
where
lower(data -> 'SubscriptionInfo' ->> 'Value')::jsonb #> lower('[{"firstname": "paolo"}]')::jsonb;
Use cross join and extract JSON then use ilike
select distinct on (t.id) t.*
from
test t
cross join jsonb_array_elements(data -> 'SubscriptionInfo' -> 'Value') ej
where
value ->> 'firstname' ilike '%paolo%';
If you are using Postgres 13 or later, you can use a SQL/JSON path expression:
select t.*
from the_table t
where t.data ## '$.SubscriptionInfo.Value[*].firstname like_regex "paolo" flag "i"'

Query all objects within json array

I'm looking to do a query on a column in my database but the column is of type jsonb. This is an example of the structure:
select json_column->>'left' from schema.table;
[{"id": 123, "name": "Joe"},
{"id": 456, "name": "Jane"},
{"id": 789, "name": "John"},
{"id": 159, "name": "Jess"}]
Essentially I'm just trying to return all the name fields from this but I can't figure it out.
I have tried
select json_column->'left'->>'name' from schema.table
But this returns a blank value just.
I have also tried:
select elem->>'name'
from schema.table m,
jsonb_array_elements(json_column->'left') elem;
But that gives me:
ERROR: cannot extract elements from an object
This seems to work when I have a where clause inserted, for example:
select elem->>'name'
from schema.table m,
jsonb_array_elements(json_column->'left') elem
where m.id = 1;

how to read key/value from a column which values are JSON type in postgreSQL

I'm trying to read the column which type is json, values in column look like this
column1
---------------------------------------------
"[{'name': 'Kate', 'position': 'painter'}]"
Im using this query, but all I get is null, what can I do to get the values for each keys?
SELECT
column1 ->> 'name' AS name
FROM
table1;
Then you use jsonb_pretty that Returns from_json as indented JSON text.
select jsonb_pretty('[{"name": "Kate", "position": "painter"}]');
Output display you:
jsonb_pretty
-------------------------------
[ +
{ +
"name": "Kate", +
"position": "painter"+
} +
]
so in your case you use
SELECT jsonb_pretty(column1) AS name FROM table1;
Use json_array_elements function:
SELECT json_array_elements(t) -> 'name'
FROM table1;

JSONB sort aggregation

I found this query that suits my needs thanks to this answer here in order to sort fields of data in a JSON document.
(Fake, generated random data)
SELECT jsonb_agg(elem)
FROM (
SELECT *
FROM jsonb_array_elements('[{
"id": "1",
"first_name": "Maximo",
"last_name": "Sambiedge",
"email": "msambiedge0#economist.com",
"gender": "Male",
"ip_address": "242.145.232.65"
}, {
"id": "2",
"first_name": "Maria",
"last_name": "Selland",
"email": "aselland1#sitemeter.com",
"gender": "Female",
"ip_address": "184.174.58.32"
}]') a(elem)
ORDER BY (elem->>'email') -- order by integer value of "ts"
) sub;
As we can see, this works with hardcoded data which doesn't quite fit my needs. I can't seem to figure out how to replace the JSON data with the jsonb column in my table.
My attempt below yields 'data is not defined'
SELECT jsonb_agg(elem), (SELECT data FROM file_metadata)
FROM (
SELECT *
FROM jsonb_array_elements(data) a(elem)
ORDER BY (elem->>'email')
) sub;
My suspicions are that a subquery is needed inside the FROM clause?
Here is a SQLFiddle of my issue to help describe the table and how the structure is defined: http://sqlfiddle.com/#!17/41102/92
You are almost there. You just need to bring in the original table, like so:
SELECT jsonb_agg(elem)
FROM (
SELECT elem
FROM file_metadata, jsonb_array_elements(data) a(elem)
ORDER BY (elem->>'email')
) sub;
Updated DB Fiddle

Postgres JSONB do a select from an array of data

I'm using a Postgres database and I'm trying to use the new JSONB type. I have a table named employees with a column named previous_companies that contains the following JSON data:
[{"company":"Facebook", "link": "www.facebook.com"}, {"company":"Google", "link": "www.google.com"}, {"company":"Some Face", "link": "www.someface.com"}]
I'm trying to select all the employees that have certain string for the field "company", for example:
If I want all the employees that worked on a company, that has "face" on it's name I would have:
[{"company":"Facebook", "link": "www.facebook.com"}, {"company":"Some Face", "link": "www.someface.com"}]
I was able to do a query for the EXACT string, like this:
SELECT * FROM employees WHERE previous_companies #> '[{"company":"Facebook"}]'
but it returns this: [{"company":"Facebook", "link": "www.facebook.com"}]
As you can see this does not support querying for incomplete strings.
Thanks!
jsonb_array_elements() function may be helpful for querying by array JSONB column:
SELECT
id,
to_jsonb(array_agg(previous_company)) AS previous_companies
FROM (
SELECT
id,
jsonb_array_elements(previous_companies) AS previous_company
FROM ( VALUES
('id1', '[{"company":"Facebook", "link": "www.facebook.com"},{"company":"Google", "link": "www.google.com"}, {"company":"Some Face", "link": "www.someface.com"}]'::jsonb),
('id2', '[{"company":"Some Face", "link": "www.someface.com"}]'::jsonb),
('id3', '[{"company":"Google", "link": "www.google.com"}]'::jsonb)
) employees (id, previous_companies)
) T
WHERE
lower(previous_company->>'company') LIKE '%face%'
GROUP BY
id
;