Ваша проблема в том, что вы хотите, чтобы родительские категории были в разных столбцах, что усложняет задачу, чем она могла бы быть.
Один из вариантов сокращения запроса и предотвращения множественных объединений использует условную агрегацию:
with rcte as (...)
select
max(case when level = 0 then parent_id end) parent_id_0,
max(case when level = 0 then category_id end) category_id_0,
max(case when level = 0 then category end) category_0,
max(case when level = 1 then parent_id end) parent_id_1,
max(case when level = 1 then category_id end) category_id_1,
max(case when level = 1 then category end) category_1,
...
from rcte
Вы можете добавить больше троек условных выражений, чтобы управлять максимальным количеством уровней по мере необходимости; когда фактическая иерархия продукта исчерпывается, следующие столбцы останутся пустыми.
Другой вариант - агрегирование строк. Это создает уникальный столбец для каждого исходного столбца, в котором все значения объединяются в порядке, в котором они появляются в иерархии:
with rcte as (...)
select
string_agg(parent_id, ' > ') within group(order by level) parent_ids,
string_agg(category_id_id, ' > ') within group(order by level) category_ids,
string_agg(category, ' > ') within group(order by level) categories
from rcte