0

Let's say I have an email feature and I need to select the recipients of an email.

users table has columns: id, full_name

emails table has columns: id, subject, body,sender_id, recipient_id

Pseudo code is

SELECT
  e.id AS email_id,
  e.subject AS email_subject,
  u_sender.full_name AS sender_name,
  u_recipient.full_name AS recipient_name
FROM emails e
LEFT JOIN users u_sender
  ON e.sender_id = u_sender.id
LEFT JOIN users u_recipient
  ON e.recipient_id = u_recipient.id

This will return something like:

| email_id | email_subject | sender_name | recipient_name |
|     1        |         Hello        |       John         |        Steve          |
|     1        |         Hello        |       John         |        Mark          |
|     1        |         Hello        |       John         |        Peter          |

Instead, is there a way to get something like:
| email_id | email_subject | sender_name | recipient_name |
|     1        |         Hello        |       John         |   [Steve, Peter, Mark]  |

Notice that they have the same email_ids because my application can send the email to multiple recipients.

I found a similar question but the solution is apache-exclusive.

I also found a response that uses XML PATH here but it's for SQL Server 2005. I'm using postgres.

Thanks in advance.

reiallenramos
  • 1,235
  • 2
  • 21
  • 29

2 Answers2

2

PostgreSQL 9 provides the string_agg aggregation function to flatten multiple values into a single string. In your example, it would be string_agg(u_recipient.full_name, ',') along with a suitable group by:

select
  e.id email_id,
  e.subject email_subject,
  u_sender.full_name sender_name,
  string_agg(u_recipient.full_name, ',') recipient_name
from emails e
left join users u_sender
  on e.sender_id = u_sender.id
left join users u_recipient
  on e.recipient_id = u_recipient.id
group by email_id, email_subject, sender_name
jspcal
  • 50,847
  • 7
  • 72
  • 76
0

Use a GROUP BY clause with email_id, email_subject, sender_name and call STRING_AGG(recipient_name, ',')

You will have something like this:

SELECT email_id, email_subject, sender_name, string_agg(recipient_name, ',') FROM test GROUP BY email_id, email_subject, sender_name

With your query:

WITH X AS 
(
SELECT
  e.id AS email_id,
  e.subject AS email_subject,
  u_sender.full_name AS sender_name,
  u_recipient.full_name AS recipient_name
FROM emails e
LEFT JOIN users u_sender
  ON e.sender_id = u_sender.id
LEFT JOIN users u_recipient
  ON e.recipient_id = u_recipient.id
)
SELECT email_id, email_subject, sender_name, string_agg(recipient_name, ',') FROM X GROUP BY email_id, email_subject, sender_name;
Diego Victor de Jesus
  • 2,575
  • 2
  • 19
  • 30