Postgres: Loop through json array equivalent in SQL? - sql

I am using postgres 9.6.3 and need to convert the following python code to a sql query:
data = response.json()
activities = data['Response']['data']['activities']
for activity in activities:
activityHash = int(activity['activityHash'])
if activityHash == 2659248071:
clears = int(activity['values']['activityCompletions']['basic']['value'])
The table has two columns: (membershipid integer primary key, data jsonb). I am not sure how to handle an array like this in sql. The array is variable length and might or might not include an entry where activityHash == the desired value.
The desired result from the query would be something like SELECT membershipid, clears FROM table.

I was looking for jsonb_array_elements(activities)

I recommend you check out this link that walks you through how to traverse JSONB in Postgres.
Try the following query and see if that works for you:
SELECT
membershipid,
'data' -> 'activity' -> 'response' -> 'data' -> 'activities' ->> 'activityHash' AS activityHash,
'data' -> 'activity' -> 'response' -> 'data' -> 'activities' -> 'activityHash' -> 'values' -> 'activityCompletions' -> 'basic' ->> 'value' AS clears
FROM yourtablename
WHERE
('data' -> 'activity' -> 'response' -> 'data' -> 'activities' ->> 'activityHash')::int = 2659248071;

Related

POSTGRESQL : select data with where clause condition from object in json data type

I have data in database from tabel data_for_filter and column src_data (type: JSON) like this
{"filter": {"name": "Anton", "activity": "Studying"},"primary": true, "position": 1}
in postgresql, how I can do search query with where clause name like '%Here%' ?
i was try this query
select src_data from data_for_filter where src_data ->> 'filter' #>> 'name' like '%Here%'
->> returns a text, so you can't apply #>> on that. -> returns a proper jsonb (or json) value. The #>> operator however requires an array, so #>> 'name' would lead to the next error
where src_data -> 'filter' ->> 'name' like '%Here%'
you can simplify this using:
where src_data #>> '{filter,name}' like '%Here%'
Unless I’m misunderstanding, you’re wanting to get the JSON object field by the key “filter”, so you’re using the incorrect operator. Try -> ‘filter’
Here’s a reference:
https://www.postgresql.org/docs/current/functions-json.html

how to query for values in a deep nested json array in Postresql?

I have a column of json objects (jsonb type) in Posgresql in this format:
[ {"qos1": [ {
"country_id" : [{"id":"IT",...}, {"id":"FR",...},...]
},...],...}
...]
So I am dealing with deep nested arrays of jsons.
I need to retrieve the row containing qos1 -> country_id -> id:"FR"
How to do this?
I tried different combinations such as:
SELECT *
FROM mytable
WHERE datacolumn -> 'qos1' -> 'country_id' -> 'id' = '"FR"'
with no luck.
You can use a JSON path expression:
select *
from the_table
where datacolumn ## '$.qos1[*].country_id[*].id == "FR"'

Is it possible to add index values to the rows of a postgreSQL query when expanding JSON array with json_array_elements?

I have a database of resume data in json format which I am trying to transform.
One of the sections in each jsib is work_history, this is in the form of a json array i.e.
"work_experience":[
{
"job_title":"title",
"job_description":"description"
},
{
"job_title":"title",
"job_description":"description"
}
]
I am iterating over each resume (json file) and importing this data into a new table using dbt and postgreSQL with each element of the array being a new row with the associated metadata of the resume. Here is the code I used for this
select
json_array_elements(rjt.raw_json::json -> 'data' -> 'work_experience') as we,
json_array_elements(rjt.raw_json::json -> 'data' -> 'work_experience') -> 'job_title' as "name",
rjt.uuid as uuid
from raw_json_table rjt
The last thing that I need to do is add a column that lists the index that each job came from within its individual workexperience array i.e. if a job was the third element in the array it would have a 2 in the "source_location" column. How can I generate this index such that it starts at 0 for each new json file.
Move the function to the FROM clause (where set-returning functions should be used). Then you can use with ordinality which also returns a column that indicates the index inside the array
select w.experience as we,
w.experience ->> 'job_title' as "name",
w.experience ->> 'job_description' as "description",
w.idx as "index",
rjt.uuid as uuid
from raw_json_table rjt
left join json_array_elements(rjt.raw_json::json -> 'data' -> 'work_experience') with ordinality
as w(experience, idx) on true
The left join is necessary so that rows from raw_json_table that don't contain array elements are still included.

PostgreSQL: select from field with json format

Table has column, named "config" with following content:
{
"A":{
"B":[
{"name":"someName","version":"someVersion"},
{"name":"someName","version":"someVersion"}
]
}
}
The task is to select all name and version values. The output is expected selection with 2 columns: name and value.
I successfully select the content of B:
select config::json -> 'A' -> 'B' as B
from my_table;
But when I'm trying to do something like:
select config::json -> 'A' -> 'B' ->> 'name' as name,
config::json -> 'A' -> 'B' ->> 'version' as version
from my_table;
I receive selection with empty-value columns
If the array size is fixed, you just need to tell which element of the array you want to retrieve,e.g.:
SELECT config->'A'->'B'->0->>'name' AS name,
config->'A'->'B'->0->>'version' AS version
FROM my_table;
But as your array contains multiple elements, use the function jsonb_array_elements in a subquery or CTE and in the outer query parse the each element individually, e.g:
SELECT rec->>'name', rec->>'version'
FROM (SELECT jsonb_array_elements(config->'A'->'B')
FROM my_table) j (rec);
Demo: db<>fiddle
First you should use the jsonb data type instead of json, see the documentation :
In general, most applications should prefer to store JSON data as
jsonb, unless there are quite specialized needs, such as legacy
assumptions about ordering of object keys.
Using jsonb, you can do the following :
SELECT DISTINCT ON (c) c->'name' AS name, c->'version' AS version
FROM my_table
CROSS JOIN LATERAL jsonb_path_query(config :: jsonb, '$.** ? (exists(#.name))') AS c
dbfiddle
select e.value ->> 'name', e.value ->> 'version'
from
my_table cross join json_array_elements(config::json -> 'A' -> 'B') e

PostgreSQL: How to use -> and ->> to search SQL JSON?

The below is the json in my 'details' column in a postgreSQL DB. I am trying to do a login check to return the username which matches the password.
{
"id":"11a8581b-b56f-426e-92f6-a426ba635b98",
"firstName":"Ryan",
"lastName":"Bob",
"username":"ryan",
"address":"Flat 7, 8 Clisssld Road, London, N16 9AB",
"email":"ryan#abc.com",
"password":"$s0$e0801$M/lNYD/JsVN4FoOjs7BwBA==$+C3+A9lAYPMd1YM0FsSbaIzw0wFito4OSEvSrMM/34k="
}
SELECT details -> 'username'
FROM users WHERE
details -> 'password' = '$s0$e0801$M/lNYD/JsVN4FoOjs7BwBA==$+C3+A9lAYPMd1YM0FsSbaIzw0wFito4OSEvSrMM/34k=';
PostgreSQL provides two native operators -> and ->> to help you query JSON data.
The operator -> returns JSON object field as JSON.
The operator ->> returns JSON object field as text.
I think this link could be really helpful in your case.