'Postgres Subquery - How to create ALIAS in object format from subqueries

I am trying to wrap several queries into 1 complex query.

Here is the scenario. Given a user_id of 'xxxxx-xx-xxxxx' I have to query for several data points within several tables. I have most of the queries below wrapped up with some JOIN(s) but would really like to see if its possible to get the last queries where I am getting the users name and email wrapped into an ALIAS column stored as an object? I am not sure if it's possible but here are the queries broken down..

THE LONG WAY

Query 1:

SELECT * FROM requests WHERE created_by = 'xxxx-xx-xxxxx';

This query will return a row as such:

id   |   created_by   |   created_date ...
1141   xxxx-xx-xxxxx    2019-04-09 19:33:40.889+00 ...

I then have to run another query to find all approvers for the returned id Query 2:

SELECT * FROM approvers WHERE request_id = 1141

This could possibly return many rows as such:

request_id   |   user_id      |   decision    |    type   | .....
1141            xxxxx-xx-xxxxx       approve         approver     ......
1141            aaaaa-aa-aaaaa      approve         approver     ......
1141            bbbbb-bb-bbbbb    under review      watcher     ......
1141            ccccc-cc-ccccc      reject          approver     .......

and finally to find the users name I have to run queries (for each returned row of Query 2) Query 3,4,5,6:

SELECT * FROM users WHERE id = 'xxxx-xx-xxxxx' LIMIT 1

will return:

id           |     given_name     |     family_name     |     email     | .....
xxxx-xx-xxxxx      John                  Doe             [email protected]    ....

Is it possible to run a subquery and create an ALIAS column of approver_info with the associated approvers and users stored as a JSON object as such?

Desired Query / Result:

1 Query:

SELECT * FROM requests
WHERE created_by = 'xxxxx-xx-xxxxx'
SUBQUERY HERE ...

That will produce the following result:

id   |  created_by    |  created_date               |  approver_info    ...
1141    xxxx-xx-xxxxx    2019-04-09 19:33:40.889+00    [{"id" : "xxxxx-xx-xxxxx", "given_name" : "John", "family_name" : "Doe", "email":"[email protected]","decision" : "approve", "type" : "approver"},
                                                        {"id" : "aaaaa-aa-aaaaa", "given_name" : "Sansa", "family_name" : "Stark", "email":"[email protected]","decision" : "approve", "type" : "approver"},
                                                        {"id" : "bbbbb-bb-bbbbb", "given_name" : "Arya", "family_name" : "Stark", "email":"[email protected]","decision" : "under review", "type" : "watcher"},
                                                        {"id" : "ccccc-cc-ccccc", "given_name" : "Ned", "family_name" : "Stark", "email":"[email protected]","decision" : "approve", "type" : "approver"}]


Solution 1:[1]

Your query could look like this:

SELECT r.id, r.created_by, r.created_date
    , (SELECT json_agg(au)
       FROM  (
          SELECT u.id, u.given_name, u.family_name, u.email, a.decision, a.type -- , ...
          FROM   approvers a
          JOIN   users     u ON u.id = a.user_id
          WHERE  a.request_id = r.id
          ) au
      ) AS approver_info
FROM   requests  r
WHERE  r.created_by = 'xxxx-xx-xxxxx';

Using a correlated subquery to aggregate 0-n related rows into the JSON array approver_info.

A LATERAL join would be an equivalent alternative:

The nested subquery is one way to build the JSON array with original column names as keys. There are others (with json_build_object() or row_to_json()):

Solution 2:[2]

seems you are looking for join

SELECT * 
FROM requests r
INNER JOIN  approvers a on r.id = a.id 
INNER JOIN users u on u.id = r.user_id 
WHERE r.created_by = 'xxxx-xx-xxxxx';

and if you need some part of the row result as json you could try using row_to_json()

select r.user_id, r.request_id,  row_to_json(row(your_col1,your_col2,.....))
FROM requests r
INNER JOIN  approvers a on r.id = a.id 
INNER JOIN users u on u.id = r.user_id 
WHERE r.created_by = 'xxxx-xx-xxxxx';

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2