Иногда возникает необходимость объединить в одной ячейке несколько записей. В моём последнем случае это был заказ от программистов: «Нам необходимо представление (view), которое в первой ячейке содержит ID пользователя, а во второй – массив из текстовых наименований групп, участником которых является пользователь».
Спорить порой бесполезно, проще сделать что просят (на это есть свои причины).
Почти уже собравшись реализовывать «самописную» агрегатную функцию, поступил с точностью наоборот. Я уже обновился с PostgreSQL 8.3 до версии 8.4, поэтому первым делом сходил почитать пункты нововведений более внимательно (а не только в разрезе той функциональности, которая ожидалась с нетерпением). Через две минуты была найдена новая функция array_agg(), которая дословно «input values concatenated into an array» (пер.: «объединяет входящие значения в массив»).
В результате всё действия свелись к созданию представления, в котором каждая строка это ID пользователя и имя группы:
user_group_names_v
И вот он запрос для представления, осчастлививший моих кодеров:
В результате получаем:
P.S.: На самом деле у меня всё обошлось одним представлением, но для упрощения понимания я добавил user_group_names_v.
P.P.S: На чтение документации и реализацию у меня ушло меньше времени, чем на написание этой статьи.
Спорить порой бесполезно, проще сделать что просят (на это есть свои причины).
Почти уже собравшись реализовывать «самописную» агрегатную функцию, поступил с точностью наоборот. Я уже обновился с PostgreSQL 8.3 до версии 8.4, поэтому первым делом сходил почитать пункты нововведений более внимательно (а не только в разрезе той функциональности, которая ожидалась с нетерпением). Через две минуты была найдена новая функция array_agg(), которая дословно «input values concatenated into an array» (пер.: «объединяет входящие значения в массив»).
В результате всё действия свелись к созданию представления, в котором каждая строка это ID пользователя и имя группы:
user_group_names_v
-------------------- user_id | group_name -------------------- 1 | test 1 | admin 1 | user 2 | user 2 | test --------------------
И вот он запрос для представления, осчастлививший моих кодеров:
select user_id, array_agg(group_name) as group_names from user_group_names_v group by user_id;
В результате получаем:
----------------------------- user_id | group_names ----------------------------- 1 | {admin, test, user} 2 | {test, user} -----------------------------
P.S.: На самом деле у меня всё обошлось одним представлением, но для упрощения понимания я добавил user_group_names_v.
P.P.S: На чтение документации и реализацию у меня ушло меньше времени, чем на написание этой статьи.