您需要將列變爲行,這意味着您需要將它們取消轉換。我定義爲一個表工作:
create table t42(id number, colour1 varchar2(5), colour2 varchar2(5),
colour3 varchar2(5), colour4 varchar2(5));
有了您的兩行數據,您可以在UNPIVOT至10行,每行每列一個:
select *
from (
select id, to_char(id) as cid, colour1, colour2, colour3, colour4
from t42
)
unpivot (val for col in (cid, colour1, colour2, colour3, colour4));
ID COL VAL
---------- ------- ----------------------------------------
105 CID 105
105 COLOUR1 blue
105 COLOUR2 green
105 COLOUR3 black
105 COLOUR4 red
106 CID 106
106 COLOUR1 red
106 COLOUR2 green
106 COLOUR3 white
106 COLOUR4 red
然後可以有效地重新-pivot在於:
select col,
max(case when rn = 1 then val end) as val1,
max(case when rn = 2 then val end) as val2
from (
select u.*, row_number() over (partition by u.col order by u.id) as rn
from (
select id, to_char(id) as cid, colour1, colour2, colour3, colour4
from t42
) unpivot (val for col in (cid, colour1, colour2, colour3, colour4)) u
)
group by col;
COL VAL1 VAL2
------- ----- -----
CID 105 106
COLOUR1 blue red
COLOUR2 green green
COLOUR3 black white
COLOUR4 red red
我添加了一個row_number
僞列到逆透視結果,並且使用了將值分爲兩列中的一個;然後使用max
摺疊空值。
然後你只需要鬆帕雷在兩列中的值:
select val1, val2,
case when val1 = val2 then 'same' else 'notsame' end as compare
from (
select col,
max(case when rn = 1 then val end) as val1,
max(case when rn = 2 then val end) as val2
from (
select u.*, row_number() over (partition by u.col order by u.id) as rn
from (
select id, to_char(id) as cid, colour1, colour2, colour3, colour4
from t42
) unpivot (val for col in (cid, colour1, colour2, colour3, colour4)) u
)
group by col
);
VAL1 VAL2 COMPARE
----- ----- -------
105 106 notsame
blue red notsame
green green same
black white notsame
red red same
如果您添加更多的列你只需要修改內逆轉置部分。
我說你有效地重新擺動,但你實際上也可以重新擺動;我想這另一條路看起來impler,persoanlly,但這可能有更好的表現和意見無論如何都會有所不同:
select a_val, b_val,
case when a_val = b_val then 'same' else 'notsame' end as compare
from (
select * from (
select col, val, rn
from (
select u.*, row_number() over (partition by u.col order by u.id) as rn
from (
select id, to_char(id) as cid, colour1, colour2, colour3, colour4
from t42
) unpivot (val for col in (cid, colour1, colour2, colour3, colour4)) u
)
)
pivot (max(val) as val for (rn) in (1 as a, 2 as b))
);
A_VAL B_VAL COMPARE
----- ----- -------
105 106 notsame
blue red notsame
green green same
black white notsame
red red same
如果ID(或不管他們是)是固定的,你可以用這些代替rn
,但我得到他們可能改變的印象。
作爲一個未經區分的變體,您可以比較不同列中的值,排序。說的數據是建立這樣的:
insert into t42 values (105, 'blue', 'green', 'black', 'red');
insert into t42 values (106, 'red', 'green', 'white', 'blue');
...所以現在兩行既有red
和blue
,但在不同的列。你可以排名基於其名稱的值,而不是使用列名:
select val1, val2,
case when val1 = val2 then 'same' else 'notsame' end as compare
from (
select col_rnk,
max(case when rn = 1 then val end) as val1,
max(case when rn = 2 then val end) as val2
from (
select u.*,
row_number() over (partition by u.col order by u.id) as rn,
rank() over (order by case when u.col = 'CID' then null else u.val end)
as col_rnk
from (
select id, to_char(id) as cid, colour1, colour2, colour3, colour4
from t42
) unpivot (val for col in (cid, colour1, colour2, colour3, colour4)) u
)
group by col_rnk
)
order by val1;
VAL1 VAL2 COMPARE
----- ----- -------
105 106 notsame
black notsame
blue blue same
green green same
red red same
white notsame
我剛加入的col_rnk
僞列;有一個ID列的特殊情況,但你可能不希望那樣顯示。將black
和white
或任何其他不匹配的對放入相同的結果行將需要另一個級別的操作。
你是說你的表永遠不會超過2行嗎? – OldProgrammer
那就對了。即使列數可能變化,我也不會超過兩行。 – user2524274