2

There are two tables in relation one-to-many:

CREATE TABLE user (
  id bigserial PRIMARY KEY,
  name varchar(255) NOT NULL UNIQUE,
)

CREATE TABLE user_pets (
  id bigserial PRIMARY KEY,
  user_id int8 FOREIGN KEY REFERENCES user(id),
  name varchar(255)
)

user.id is generated by DEFAULT.

Another table containing json of users and their pets:

CREATE TABLE user_json (
  user_id int8 FOREIGN KEY REFERENCES user(id),
  full_info json
)

I want my json look like this:

{
  "id": 1,
  "name": "John",
  "pets": [
    {
      "id": 1,
      "user": 1,
      "name": "Kitty"
    },
    {
      "id": 2,
      "user": 1,
      "name": "Cat"
    }
  ]
}

I'm using json_build_object to process user, but I don't know how to convert multiple rows to array of pets:

json_build_object(
  'id', user.id,
  'name', user.name,
  'pets', --WHAT SHALL I PASS HERE?
)

Postgres 10

2 Answers 2

4

In the end, this worked for me:

WITH all_pets AS (
  SELECT *
  FROM pets
  WHERE pets.user_id = 1
)
INSERT INTO user_json (full_info)
SELECT
json_build_object(
  'id', user.id,
  'name', user.name,
  'pets', (
    SELECT json_agg(all_pets)
    FROM pets
  )
)
FROM user
WHERE user.id = 1;
1

You can use json_to_recordset(), and apply it to your json object using a CROSS JOIN LATERAL:

SELECT a.full_info->>'id', a.full_info->>'name', b.*
FROM user_json a
CROSS JOIN lateral json_to_recordset(a.full_info->'pets')
as b("id" integer
      , "user" integer
      , "name" varchar)
2
  • when i pass this query into json_build_object function, i get ERROR: subquery must return only one column. I need json info of user containing array of pets, but i don't see any user data in your query. I'm sorry, I don't get it, how it works Commented Dec 4, 2017 at 8:25
  • Weird because it works on my instance when I insert the JSON string: SELECT a.full_info->>'id', a.full_info->>'name', b.* FROM (SELECT '{ "id": 1, "name": "John", "pets": [ { "id": 1, "user": 1, "name": "Kitty" }, { "id": 2, "user": 1, "name": "Cat" } ]}'::json as full_info) a CROSS JOIN lateral json_to_recordset(a.full_info->'pets') as b("id" integer , "user" integer , "name" varchar) Commented Dec 4, 2017 at 19:03

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.