Попробуйте следующий запрос:
WITH test_table AS(
SELECT *
FROM (VALUES
(1, 123, 234, 7),
(2, 123, 234, 8),
(3, 123, 234, 9),
(4, 234, 567, 17),
(5, 234, 567, 16),
(6, 234, 567, 15)
) AS T (id, field1, field2, value)
)
SELECT
MIN(id) as min_id,
MAX(id) as max_id,
field1,
field2,
STRING_AGG(value, '; ')profit
FROM test_table
GROUP BY field1, field2 --тут можно и id добавить,
--но думаю общий смысл понятен
Должно сработать, правда это не на всех версиях постгреса работает. Есть альтенативные решения для более ранних версий. Напишите, если не получилось.

UPD не обращайте внимания на сортировку, тут она по умолчанию, как оптимизатор строки обрабатывает. Но можно задать при желании пользовольскую в предложении STRING_AGG
Почитайте:
https://www.postgresqltutorial.com/postgresql-aggregate-functions/postgresql-string_agg-function/