1

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             johndoe@email.com    ....

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":"john@email.com","decision" : "approve", "type" : "approver"},
                                                        {"id" : "aaaaa-aa-aaaaa", "given_name" : "Sansa", "family_name" : "Stark", "email":"sansa@.com","decision" : "approve", "type" : "approver"},
                                                        {"id" : "bbbbb-bb-bbbbb", "given_name" : "Arya", "family_name" : "Stark", "email":"arya@email.com","decision" : "under review", "type" : "watcher"},
                                                        {"id" : "ccccc-cc-ccccc", "given_name" : "Ned", "family_name" : "Stark", "email":"ned@email.com","decision" : "approve", "type" : "approver"}]
Community
  • 1
  • 1
Louie
  • 5,920
  • 5
  • 31
  • 45
  • 1
    Your version of Postgres and actual, basic table definitions (`CREATE TABLE` statements) would be instrumental. Assuming `users.id` is the primary key of the table, so why `LIMIT 1`? – Erwin Brandstetter Jun 23 '19 at 22:46

2 Answers2

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()):

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
0

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';
ScaisEdge
  • 131,976
  • 10
  • 91
  • 107
  • thanks for the quick reply scaisEdge. I am actually doing a JOIN on most of the query above... but I am curious to see if I can get all of the associated users for the request id into an ALIAS stored as a JSON object. You can see an example of the desired query result at the bottom of the question. Thanks again! – Louie Jun 23 '19 at 16:22
  • answer updated . woth a suggestion ...hope is useful – ScaisEdge Jun 23 '19 at 16:28
  • yeah it will definitely be useful. Thanks! – Louie Jun 23 '19 at 16:30