Если у вас есть только одно значение на столбец, то я думаю, что более простое решение состоит в перечислении значений и агрегировании:
select max(a) as a, max(b) as b, max(c) as c
from (select t.*,
dense_rank() over (partition by (case when a is null then 1 else 2 end),
(case when b is null then 1 else 2 end),
(case when c is null then 1 else 2 end)
order by a, b, c
) as seqnum
from t
) t
group by seqnum;
Это «агрегирует» только один раз и использует только одну оконную функцию, поэтому я думаю, что он должен иметь лучшую производительность, чем обработка каждого столбца в отдельности.
Другой подход заключается в использовании боковых объединений, которые доступны в Oracle 12 C - но это предполагает совместимость типов:
select max(case when which = 'a' then val end) as a,
max(case when which = 'b' then val end) as b,
max(case when which = 'c' then val end) as c
from (select which, val,
dense_rank() over (partition by which order by val) as seqnum
from t cross join lateral
(select 'a' as which, a as val from dual union all
select 'b', b from dual union all
select 'c', c from dual
) x
where val is not null
) t
group by seqnum;
Производительность может быть сопоставимой, поскольку подзапрос удаляет так много строк.