您需要将列放入行中,这意味着您需要取消透视它们。我正在使用定义为的表:
create table t42(id number, colour1 varchar2(5), colour2 varchar2(5),
colour3 varchar2(5), colour4 varchar2(5));
使用您的两行数据,您可以将其取消透视到 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
然后,您可以有效地重新调整:
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
在 unpivot 结果中添加了一个伪列,并用它来将值拆分为两列之一;然后用于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
如果您添加更多列,您只需要修改内部 unpivot 部分。
我说你有效地重新旋转,但实际上你也可以重新旋转;我认为另一种方式看起来更简单,个人化,但这可能会表现得更好,而且意见也会有所不同:
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
and 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
andwhite
或任何其他不匹配的对放入同一结果行将需要另一个级别的操作。