Sql 在oracle中转置和比较列值

Sql 在oracle中转置和比较列值,sql,oracle,oracle11g,transpose,Sql,Oracle,Oracle11g,Transpose,假设我有一张像这样的2x5桌子 105 blue green black red 106 red green white red 我想转置这个表,比较两列的值,并在第三列显示它们是否相同 105 106 notsame blue red notsame green green same black white notsame red red same 我用了很多“工会”尝试并实现了这一点。但是,我如何以更少的复杂性和代码大

假设我有一张像这样的2x5桌子

105 blue    green black  red
106 red     green white  red
我想转置这个表,比较两列的值,并在第三列显示它们是否相同

105     106    notsame
blue    red    notsame
green   green  same
black   white  notsame
red     red    same

我用了很多“工会”尝试并实现了这一点。但是,我如何以更少的复杂性和代码大小来完成它呢?

您希望使用pivot。你可以退房

我还没有访问11g的权限,所以我无法制作一个示例。但我知道,这正是你想要的

下面是来自该链接的SQL:

select * from (
   select times_purchased, state_code
   from customers t
)
pivot 
(
   count(state_code)
   for state_code in ('NY','CT','NJ','FL','MO')
)
order by times_purchased
这是另一个

或者更好,这里是所有的


最后,我们找到了可能有助于创建简单转置的方法。底部有2个“有用”答案。

您需要将列放入行中,这意味着您需要取消对它们的拆分。我正在使用一个定义为:

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   
我在unpivot结果中添加了一个
row\u 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    
如果添加更多的列,则只需修改内部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(或任何ID)是固定的,您可以使用它们而不是
rn
,但我觉得它们可能会改变


作为未请求的变量,您可以比较不同列中的值。假设数据设置如下:

insert into t42 values (105, 'blue', 'green', 'black', 'red');
insert into t42 values (106, 'red', 'green', 'white', '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 

我刚刚添加了
伪列;ID列有一个特殊情况,但您可能不希望显示该列。将
黑色
白色
或任何其他不匹配的对放入同一结果行需要另一个级别的操作。

您是说您的表中的行数永远不会超过2行吗?没错。即使列的数量可能会改变,我也不会得到超过两行的内容。我很难把那个例子和我的联系起来。我想我在找一些不那么复杂的东西。你能告诉我在我的例子中需要做哪些改变吗?恐怕我不知道。希望有人与11g的经验将回答。看起来像一个伟大的解决方案。谢谢所有的细节!