I have a table called cust_data which stores id and JSON object. I want to write postgres select statements to fetch:
- select all id's where "gender": "Female" is not present in persons array [this should return id#3 from below data]
- select all id's where "gender": "Female" is present and "status":"married" [this should return id#2 from below data]
Table : cust_data
id(numeric) | connections (jsonb)
------------------------------
1, {"Persons": [
{
"personName": "Tom",
"gender": "Male",
"country": "USA",
"status":"single"
},
{
"personName": "Harry",
"gender": "Male",
"country": "USA",
"status":"single"
},
{
"personName": "Lisa",
"gender": "Female",
"country": "Mexico",
"status":"single"
}
]
}
2,{
"Persons": [
{
"personName": "Lisa",
"gender": "Male",
"country": "UK",
"status":"single"
},
{
"personName": "Harry",
"gender": "Male",
"country": "USA",
"status":"single"
},
{
"personName": "Lisa",
"gender": "Female",
"country": "Mexico",
"status":"married"
}
]
}
3,{
"Persons": [
{
"personName": "Lisa",
"gender": "Male",
"country": "UK",
"status":"single"
},
{
"personName": "Harry",
"gender": "Male",
"country": "USA",
"status":"single"
}
]
}
klin
123k15 gold badges240 silver badges262 bronze badges
asked May 10, 2017 at 17:25
user842122
2952 gold badges4 silver badges18 bronze badges
-
have you looked on official postgres page: postgresql.org/docs/9.3/static/functions-json.htmlFahad Anjum– Fahad Anjum2017年05月10日 19:33:47 +00:00Commented May 10, 2017 at 19:33
-
Yes. But it pull all records. Here is the query - SELECT id from cust_data t, jsonb_array_elements(t.connections->'persons') AS elem WHERE elem->>'gender' !='female' ;user842122– user8421222017年05月10日 19:45:02 +00:00Commented May 10, 2017 at 19:45
-
please check persons. In your example it is capital letter. while in query it is written with small letter.Fahad Anjum– Fahad Anjum2017年05月10日 19:50:11 +00:00Commented May 10, 2017 at 19:50
2 Answers 2
You can use boolean aggregate functions:
select id
from cust_data,
lateral jsonb_array_elements(connections->'Persons')
group by 1
having not bool_or(value->>'gender' = 'Female');
id
----
3
(1 row)
select id
from cust_data,
lateral jsonb_array_elements(connections->'Persons')
group by 1
having bool_or(value->>'gender' = 'Female' and value->>'status' = 'married');
id
----
2
(1 row)
If the arrays may be empty you should use left join ... on true instead of lateral. Add also coalesce() with appropriate default value for aggregates as they can yield null, e.g.:
select id
from cust_data
left join jsonb_array_elements(connections->'Persons') on true
group by 1
having not coalesce(bool_or(value->>'gender' = 'Female'), false);
answered May 10, 2017 at 20:21
klin
123k15 gold badges240 silver badges262 bronze badges
Sign up to request clarification or add additional context in comments.
1 Comment
user842122
Thanks! this query is not fetching ids where persons array is empty
Query for 1:
WITH test AS (
SELECT id, jsonb_array_elements(t.connections->'Persons') AS elem
FROM cust_data t
), findFemale AS (
SELECT DISTINCT id FROM test
WHERE elem->>'gender' = 'Female'
)
SELECT id FROM cust_data
WHERE id NOT IN (select * from findFemale)
Query for 2:
WITH test as (SELECT id, jsonb_array_elements(t.connections->'Persons') AS elem
from cust_data t
) , findFemaleMarried as (
select distinct id from test
where
elem ->> 'gender' = 'Female' and elem ->> 'status' = 'married'
)
select * from findFemaleMarried
I hope above query will solve your problem.
Cheeso
193k106 gold badges486 silver badges734 bronze badges
answered May 10, 2017 at 20:04
Fahad Anjum
1,2561 gold badge10 silver badges19 bronze badges
Comments
Explore related questions
See similar questions with these tags.
lang-sql