1

Imagine a super simple table such as:

create table object (
    id INT,
    data jsonb
);

With some data:

INSERT INTO object (id, data) VALUES
  (4, '{"nodes":{"f":{"id":1}}}'), -- C
  (5, '{"nodes":{"d":{"id":2}, "e":{"id":3}}}'), -- B
  (6, '{"nodes":{"b":{"id":4}, "c":{"id":5}}}') -- A
;

I'd like to destructure the JSON and also query for children.

For example, if I do

SELECT * FROM jsonb_each('{"a":{"id":1},"b":{"id":2}}'::JSONB) as obj

I will get back:

a   {"id":1}
b   {"id":2}

I'm trying to combine this to get id properties out of the nested objects and query for children (with no luck):

SELECT
      jsonb_each(data->'nodes')
      FROM objects as objs
      WHERE id=6
      LATERAL (SELECT * FROM objects as ref WHERE ref.id = objs->'id');

I've provided an SQL fiddle if it helps: http://sqlfiddle.com/#!17/50fb2/9

EDIT:

here's an example output:

id  data
4   '{"nodes":{"f":{"id":1}}}'
5   '{"nodes":{"d":{"id":2}, "e":{"id":3}}}'

Thanks again for any insight into this!

2
  • Please, edit the question and add an example output. Commented Jun 18, 2017 at 17:34
  • @klin I just added example output above, thanks! Commented Jun 18, 2017 at 20:34

2 Answers 2

3

This query extracts ids from the jsonb objects:

select (value->>'id')::int as nested_id
from object,
jsonb_each(data->'nodes')
where id = 6;

 nested_id 
-----------
         4
         5
(2 rows)    

Use it as a derived table in join:

select o.*
from object o
join (
    select (value->>'id')::int as nested_id
    from object,
    jsonb_each(data->'nodes')
    where id = 6
    ) s
on id = nested_id;

 id |                    data                     
----+---------------------------------------------
  4 | {"nodes": {"f": {"id": 1}}}
  5 | {"nodes": {"d": {"id": 2}, "e": {"id": 3}}}
(2 rows)

or as a subquery with the operator in:

select o.*
from object o
where id in (
    select (value->>'id')::int as nested_id
    from object,
    jsonb_each(data->'nodes')
    where id = 6
    );

However, this can be also done with a lateral query (as you wanted):

select s.*
from object o,
jsonb_each(data->'nodes'),
lateral (select * from object where id = (value->>'id')::int) s
where o.id = 6;
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the response! I think it's correct, but I must be missing something very small, I took your answers and made an SQL fiddle showing the extraction is correct, however, the queries are returning 0 rows: sqlfiddle.com/#!17/6f5a3/8 - mind taking a look? could it be a bug in SQL fiddle?
I've changed the inserted data for id = 6 in the question, according to your intent I think.See: sqlfiddle.com/#!17/39440/1
Thank you, that's it! appreciate the help :)
0

Not sure, but may be you need this:

SELECT object.id, key, value 
FROM object
JOIN LATERAL jsonb_each(data->'nodes')
ON (value->>'id')::int  = object.id
WHERE 
object.id = 6

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.