SQL как «собрать» строки в одну строку - PullRequest
0 голосов
/ 28 мая 2018

Допустим, у меня есть функция электронной почты, и мне нужно выбрать получателей электронной почты.

users В таблице есть столбцы: id, full_name

emailsВ таблице есть столбцы: id, subject, body, sender_id, recipient_id

Псевдокод:

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

Это будет возвращать что-то вроде:

|email_id |email_subject |имя отправителя |имя-получателя |
|1 |Привет |Джон |Стив |
|1 |Привет |Джон |Марк |
|1 |Привет |Джон |Питер |

Вместо этого есть способ получить что-то вроде:
|email_id |email_subject |имя отправителя |имя-получателя |
|1 |Привет |Джон |[Стив, Питер, Марк] |

Обратите внимание, что они имеют одинаковые email_ids, потому что мое приложение может отправлять электронную почту нескольким получателям.

Я нашел похожий вопрос , но решение является apache-эксклюзивным.

Я также нашел ответ, который использует XML PATH здесь , но это для SQL Server 2005. Я использую postgres.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Используйте предложение GROUP BY с email_id, email_subject, sender_name и вызовом STRING_AGG (имя-получателя, ',')

У вас будет что-то вроде этого:

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

С вашим запросом:

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;
0 голосов
/ 28 мая 2018

PostgreSQL 9 предоставляет функцию агрегации string_agg для объединения нескольких значений в одну строку.В вашем примере это будет string_agg(u_recipient.full_name, ',') вместе с подходящим 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...