Proponuję najpierw zastosować funkcję UNPIVOT do wielu kolumn, a następnie użyć row_number()
aby utworzyć nowe nazwy kolumn, które będą używane w PIVOT.
Podstawową składnią unpivot będzie
select field,
value,
'value'||
to_char(row_number() over(partition by field
order by value)) seq
from yourtable
unpivot
(
value
for field in (Name, Age, Sex, DOB, col1, col2, col3)
) u;
Zobacz Skrzypce SQL z wersją demonstracyjną
. Spowoduje to przekształcenie wielu kolumn danych w wiele wierszy. Użyłem row_number()
aby utworzyć unikalną wartość dla nowych nazw kolumn, dane z tego zapytania wyglądają następująco:
| FIELD | VALUE | SEQ |
|-------|-------------------------|--------|
| AGE | 12 | value1 |
| AGE | 15 | value2 |
| COL1 | aa | value1 |
| COL1 | xx | value2 |
Następnie możesz zastosować funkcję PIVOT do tego wyniku:
select field, value1, value2
from
(
select field,
value,
'value'||
to_char(row_number() over(partition by field
order by value)) seq
from yourtable
unpivot
(
value
for field in (Name, Age, Sex, DOB, col1, col2, col3)
) u
) d
pivot
(
max(value)
for seq in ('value1' as value1, 'value2' as value2)
) piv
Zobacz Skrzypce SQL z wersją demonstracyjną . Daje to ostateczny wynik:
| FIELD | VALUE1 | VALUE2 |
|-------|-------------------------|-------------------------|
| AGE | 12 | 15 |
| COL1 | aa | xx |
| COL2 | bb | yy |
| COL3 | cc | zz |
| DOB | 07-Aug-2001 12:00:00 AM | 26-Aug-2001 12:00:00 AM |
| NAME | A | B |
| SEX | F | M |
Zwróć uwagę, że podczas stosowania funkcji unpivot typ danych wszystkich kolumn musi być taki sam, więc może być konieczne przekonwertowanie danych w podzapytaniu, zanim będzie można je unpivot.
Funkcja UNPIVOT/PIVOT została wprowadzona w Oracle 11g, jeśli używasz Oracle 10g, możesz edytować zapytanie, aby użyć:
with cte as
(
select 'name' field, name value
from yourtable
union all
select 'Age' field, Age value
from yourtable
union all
select 'Sex' field, Sex value
from yourtable
union all
select 'DOB' field, DOB value
from yourtable
union all
select 'col1' field, col1 value
from yourtable
union all
select 'col2' field, col2 value
from yourtable
union all
select 'col3' field, col3 value
from yourtable
)
select
field,
max(case when seq = 'value1' then value end) value1,
max(case when seq = 'value2' then value end) value2
from
(
select field, value,
'value'||
to_char(row_number() over(partition by field
order by value)) seq
from cte
) d
group by field;
Zobacz Skrzypce SQL z wersją demonstracyjną