2013-07-26 2 views
1

이렇게 2x5 테이블이 있다고 가정하십시오.oracle의 열 값을 조 변경하고 비교하십시오.

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 

는 I 시도 제 column.Like 동일한 경우 표시 할 및 로트를 이용하여이를 달성 "노조". 하지만 덜 복잡하고 코드 크기는 어떻게해야합니까?

+1

테이블에 행이 2 개 이상 표시되지 않는다고 말씀 하시겠습니까? – OldProgrammer

+0

그게 맞아. 열의 수가 바뀔지라도 2 개 이상의 행을 가져 오지 않습니다. – user2524274

답변

1

행을 열로 가져와야합니다. 따라서 행을 열 해제해야합니다. 내가 정의 테이블 함께 일하고 있어요 :

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          

그런 다음 효과적으로 다시 수 있습니다 : 데이터의 당신의 두 행으로

create table t42(id number, colour1 varchar2(5), colour2 varchar2(5), 
    colour3 varchar2(5), colour4 varchar2(5)); 

, 당신은 10 행, 행마다 열마다 하나에 피벗 해제 할 수 있습니다 그 -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 

는 난 UNPIVOT 결과에 row_number 의사 열을 첨가하고, 두 개의 열 중 하나의 값을 분할하는 것을 사용; max을 사용하여 빈 값을 축소합니다.

는 그리고 당신은 단지 두 열의 값을 sompare해야합니다

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 부분을 수정해야합니다.

나는 효과적으로 피봇 팅하고 있다고했지만 나는 실제로 다시 피벗 할 수 있다고 말했다. 나는이 다른 방법은 persoanlly, impler 보이는 생각하지만,이 더 나은 수행 할 수 있으며 의견 어쨌든 달라집니다 :

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'); 

이 ... 그래서 지금 두 행이 redblue,하지만 서로 다른 컬럼에 모두 있습니다. 당신은 오히려 열 이름을 사용하는 것보다 자신의 이름을 기준으로 값을 순위 수 : 난 그냥 col_rnk 의사 열을 추가 한

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 열에 대/소문자가 있지만 어 @ 쪽에나 표시하려는 것은 아 U니다. blackwhite 또는 다른 불일치 쌍을 같은 결과 행에 사용하려면 다른 수준의 조작이 필요합니다.

+0

멋진 솔루션 인 것 같습니다. 모든 세부 사항에 감사드립니다! – AngelWarrior

0

피벗을 사용하고 싶습니다. 체크 아웃 할 수 있습니다 Oracle info on pivot in 11g

아직 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 

다른 SO answer which may help

아니면 더 나은, 여기있는 모든 PIVOT and ORACLE tagged items on SO

그리고 마지막으로 발견 된 간단한을 만드는 데 도움이 될 another thread on Oracle's forum 바꾸어 놓다. 2 하단의 "유용한"답변.

+0

나는 그 포스트를 더 일찍 보았다. 나는 그 예를 나의 것과 관련시키는 데 약간의 어려움을 겪었다. 나는 덜 복잡한 것을 찾고 있다고 생각한다. 예제에서 변경해야 할 사항이 무엇인지 알 수 있습니까? – user2524274

+0

나는 잘 모르겠다. 바라건대 11g 경험을 가진 사람이 대답 할 수 있기를 바랍니다. – AngelWarrior

관련 문제