Если вход (и выход) - три столбца, как в вашем примере, то небольшой перебор может дать вам эффективный запрос:
select coalesce(a, b, c) as a
, case when b != a then b
when c != coalesce(a, b) then c end as b
, case when a != b and b != c and a != c then c end as c
from t
;
Требуется всего лишь мгновение, чтобы понять, почему это правильно (или, в качестве альтернативы, вы можете бросить на него множество тестовых примеров и быть удовлетворены тем, что, поскольку он дает правильный ответ во всех случаях, он должен быть правильным, даже если вы не понимаете почему это так).
Это нелегко обобщить; если бы у вас было, скажем, восемь столбцов на входе (и на выходе), вам было бы лучше с решением, подобным предложенному Ponder Stibbons. Однако обратите внимание, что количество столбцов (три, восемь или 250) должно быть известно заранее для стандартного запроса SQL; в противном случае вам нужно будет написать динамический c запрос, что обычно не считается хорошей практикой.
EDIT :
Вот решение, которое легко обобщается к любому количеству столбцов (одинаково на входе и на выходе); количество столбцов, однако, должно быть известно заранее (а также имена столбцов и их порядок).
Это решение аналогично тому, что опубликовал Ponder Stibbons. Есть два основных отличия. Во-первых, я использую предложение lateral
, которое доступно в Oracle 12.1 и выше; это позволяет выполнять вычисления отдельно в каждой строке (вместо того, чтобы смешивать все значения из всех строк вместе после unpivot
, только для того, чтобы сгруппировать их обратно в исходные строки через pivot
). Во-вторых, код немного сложнее, чтобы обрабатывать случай, когда все значения в строке null
.
select l.a, l.b, l.c
from t,
lateral (
select a, b, c
from ( select 1, row_number() over (order by nvl2(v, min(o), null)) o, v
from ( select t.a, t.b, t.c from dual )
unpivot include nulls (v for o in (a as 1, b as 2, c as 3))
group by v
)
pivot (max(v) for o in (1 as a, 2 as b, 3 as c))
) l
;
EDIT 2
В комментариях после этого ответа ОП заявляет, что его реальные данные имеют пять столбцов, а не три. Первое решение сложно расширить до пяти столбцов, но второе решение легко расширить. Показываю как на dbfiddle .