Существуют две функции агрегирования, которые должны выполнять то, что вы хотите, за исключением сохранения чисел не в виде массива, если в нем будет только один элемент.
Сначала вам нужно агрегировать числа с: json_agg(number)
, группируя поname, phone_number_of
Тогда, если вам нужно иметь одиночные телефонные номера в качестве числа / строки вместо массива, проверьте длину с помощью json_array_length(json)
, а если она меньше 2, тогда захватите первый элемент с помощью json->>0
и используйтечто вместо массива.
Когда у вас есть name, phone_number_of, number_array_or_value
, сгруппируйте их по name
и агрегируйте, используя функцию json_object_agg(key, value)
Эти агрегирующие функции описаны здесь: https://www.postgresql.org/docs/9.4/functions-aggregate.html
Пример:
select json_object_agg(name, phones)
from (
select name,
json_object_agg(typ, case when json_array_length(numbers) < 2 then numbers->0 else numbers end) as phones
from (
select name, typ, json_agg(number) as numbers
from (
select 'name1' as name, 'work' as typ, '34636432' as number
union all
select 'name1' as name, 'mobile' as typ, '12453435' as number
union all
select 'name1' as name, 'mobile' as typ, '654745' as number
union all
select 'name2' as name, 'home' as typ, '8643534434' as number
union all
select 'name3' as name, 'work' as typ, '24778457' as number
) AS sub1
group by name, typ
) AS sub2
group by name
) as sub3
group by name;
json_object_agg
--------------------------------------------------------------------------
{ "name2" : { "home" : "8643534434" } }
{ "name3" : { "work" : "24778457" } }
{ "name1" : { "work" : "34636432", "mobile" : ["12453435", "654745"] } }
(3 rows)