Search by date in array of objects within PostgreSQL JSONB Column

frbry

I have two tables in my PostgreSQL 9.6 instance.

users

+----+------------+-----------+-------------------+
| id | first_name | last_name | email             |
+----+------------+-----------+-------------------+
| 1  | John       | Doe       | [email protected] |
+----+------------+-----------+-------------------+
| 2  | Jane       | Doe       | [email protected] |
+----+------------+-----------+-------------------+
| 3  | Mike       | Doe       | [email protected] |
+----+------------+-----------+-------------------+


surveys
+----+---------+----------------------------------------------------------------------------------------------------+
| id | user_id | survey_data                                                                                        |
+----+---------+----------------------------------------------------------------------------------------------------+
| 1  | 1       | {'child_list': [{'gender': 1, 'birthday': '2015-10-01'}, {'gender': 2, 'birthday': '2017-05-01'}]} |
+----+---------+----------------------------------------------------------------------------------------------------+
| 2  | 2       | {'child_list': []}                                                                                 |
+----+---------+----------------------------------------------------------------------------------------------------+
| 3  | 3       | {'child_list': [{'gender': 2, 'birthday': '2008-01-01'}]}                                          |
+----+---------+----------------------------------------------------------------------------------------------------+

I would like be able to query these two tables to get the number of users who have children between certain age. The survey_data column in surveys table is a JSONB column.

So far I've tried using jsonb_populate_recordset with LATERAL joins. I was able to SELECT the child_list array as two columns but couldn't figure out how to use that with my JOIN between users and surveys tables. The query I used is as below:

SELECT DISTINCT u.email
FROM surveys
  CROSS  JOIN LATERAL (
   SELECT *
   FROM  jsonb_populate_recordset(null::json_type, (survey.survey_data->>'child_list')::jsonb) AS d
   ) d
INNER JOIN users u ON u.id = survey.user_id
WHERE d.birthday BETWEEN '2014-05-05' AND '2018-05-05';

This also uses a custom type which was created using this:

CREATE type json_type AS (gender int, birthday date)

My question is, is there an easier to read way to do this? I would like to use this query with many other JOINs and WHERE clauses and I was wondering if there is a better way of doing this.

Note: this is mainly going to be used by a reporting system which does not need to be super fast but of course any speed gains are welcome.

klin

Use the function jsonb_array_elements(), examples:

select email, (elem->>'gender')::int as gender, (elem->>'birthday')::date as birthday
from users u
left join surveys s on s.user_id = u.id
cross join jsonb_array_elements(survey_data->'child_list') as arr(elem)

       email       | gender |  birthday  
-------------------+--------+------------
 [email protected] |      1 | 2015-10-01
 [email protected] |      2 | 2017-05-01
 [email protected] |      2 | 2008-01-01
(3 rows)

or

select distinct email
from users u
left join surveys s on s.user_id = u.id
cross join jsonb_array_elements(survey_data->'child_list') as arr(elem)
where (elem->>'birthday')::date between '2014-05-05' and '2018-05-05';

       email       
-------------------
 [email protected]
(1 row) 

You can make your life easier using a view:

create view users_children as
    select email, (elem->>'gender')::int as gender, (elem->>'birthday')::date as birthday
    from users u
    left join surveys s on s.user_id = u.id
    cross join jsonb_array_elements(survey_data->'child_list') as arr(elem);

select distinct email
from users_children
where birthday between '2014-05-05' and '2018-05-05';

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

PostgreSQL: COUNT the occurrence of unique array values nested within a JSONB column?

PostgreSQL query on a JSONB Array of Objects

Deep search within jsonb field PostgreSQL

Postgresql JSONB object column to Array

Search by json key in jsonb column PostgreSQL

How to convert a postgresql JSONB column into array column

Postgresql query array of objects in JSONB field

Can PostgreSQL JOIN on jsonb array objects?

Update array of objects in JSONB format PostgreSQL

PostgreSQL - Add key to each objects of an JSONB array

PostgreSQL: Does jsonb sort Objects in array?

Gin Index not being used when searching in JSONB column (PostgreSQL) with an array of search terms

Query jsonb column containing array of JSON objects

PostgreSQL count results within jsonb array across multiple rows

Search among all values in PostgreSQL jsonb column using JPA Specification

How to filter records by specific attribute within jsonb field that is an array of objects

How to merge a JSONB array of objects into a single object in PostgreSQL

limit amount of objects in array of postgresql jsonb_agg

Postgresql get keys from array of objects in JSONB field

Postgresql get keys from nested array of objects in JSONB field

How to iterate over PostgreSQL jsonb array of objects and modify elements?

insert jsonb data in postgresql, option array or objects, valid way

Update the value of an attribute in a postgresql jsonb array of objects across muliple records

Postgresql remove object from jsonb array of objects by key value

Rails on JSONB 'where' multiple search terms in nested array of objects

PostgreSQL - grouping by jsonb column

Search query in jsonb column

Getting all objects in array within date range?

How to update a jsonb column in postgresql which is just an array of values and no keys