2017-02-12 96 views
1

我無法避免兩個表之間的連接結果。這兩個表的定義是:sql - 在兩個具有相同列名的表之間無法轉接連接

create table scores_jan (
    id number 
, test_1 number 
, test_2 number 
, test_3 number 
); 

create table scores_feb (
    id number 
, test_1 number 
, test_2 number 
, test_3 number 
); 

insert into scores_jan values (1, 50, 60, 70); 
insert into scores_feb values (1, 55, 65, 75); 
commit; 

我想UNPIVOT這讓一排每個ID /測試組合,達到的效果:

ID TEST_NUMBER JAN_SCORE FEB_SCORE 
1  test_1   50   55 
1  test_2   60   65 
1  test_3   70   75 

如果我寫的逆轉置不指定我感興趣的欄目,它看起來像這樣:

select * 
    from scores_jan j 
    join scores_feb f 
    on j.id = f.id 
unpivot ((jan_score, feb_score) for test_name in ((test_1, test_1) as 'test_1' 
                , (test_2, test_2) as 'test_2' 
                , (test_3, test_3) as 'test_3' 
               ) 
     ) 

這會產生錯誤ORA-00918:列定義的含糊

如果我嘗試將其與指定的列使用寫,它看起來像這樣:

select * 
    from scores_jan j 
    join scores_feb f 
    on j.id = f.id 
unpivot ((jan_score, feb_score) for test_name in ((j.test_1, f.test_1) as 'test_1' 
                , (j.test_2, f.test_2) as 'test_2' 
                , (j.test_3, f.test_3) as 'test_3' 
               ) 
     ) 

這會產生錯誤ORA-01748:這裏只允許簡單的列名

有沒有一種辦法讓這個unpivot工作?我可以將其中一個表放入子查詢中,但使用子查詢僅用於更改列的別名似乎並不理想。

+0

編輯你的問題,表明你想要達到的效果。 –

+0

@GordonLinoff預期結果已添加。 – spielchecker

+1

@spielchecker - 您正在使用哪個版本的Oracle? – GurV

回答

2
select  * 

from  (  select 'JAN_SCORE' as mth,id,test_1,test_2,test_3 from scores_jan s 
      union all select 'FEB_SCORE'  ,id,test_1,test_2,test_3 from scores_feb s 
      ) unpivot (score for test in (test_1,test_2,test_3)) 
       pivot (max(score) for mth in ('JAN_SCORE','FEB_SCORE')) 

order by test 

+----+--------+-----------+-----------+ 
| ID | TEST | JAN_SCORE | FEB_SCORE | 
+----+--------+-----------+-----------+ 
| 1 | TEST_1 | 50  | 55  | 
+----+--------+-----------+-----------+ 
| 1 | TEST_2 | 60  | 65  | 
+----+--------+-----------+-----------+ 
| 1 | TEST_3 | 70  | 75  | 
+----+--------+-----------+-----------+ 
+0

檢查更新回答 –

+0

什麼是PIVOT?我沒有看到它的問題。否則,+1意識到不需要連接;在我的書**這是正確的答案。 – mathguy

+0

@mathguy - 檢查請求的結果 - JAN的列和FEB的列 –

0

我不認爲「unpivot」是正確的方法。如果您在每個表格中每id只有一行,請使用union all或類似的方法。這裏的理念是:

select j.id, j.test_1 as test from scores_jan union all 
select j.id, j.test_2 as test from scores_jan union all 
select j.id, j.test_3 as test from scores_jan union all 
select f.id, f.test_1 as test from scores_feb union all 
select f.id, f.test_2 as test from scores_feb union all 
select f.id, f.test_3 as test from scores_feb ; 

你也應該認識到,使用單獨的表單獨個月是一個非常糟糕的想法。您應該將所有數據存儲在單個表中,並使用指定月份的列。

+1

'UNPIVOT'絕對是正確的答案 - 它需要每個表只讀一次。這個'UNION ALL'方法讀取每個表三次。 – mathguy

1

的問題,因爲你所看到的,是不明確的列名。真的有兩個問題。一個是id列。您可以使用不同的連接語法來處理它 - 而不是on j.id = f.id寫入using(id)。如果您不熟悉它,請查看此連接語法的文檔。

但是,test_1列名的歧義性不能用這種方式解決,正如你所看到的,你不能在unpivot上使用表限定符。

在這種情況下,正確的解決方案是將整個聯接作爲子查詢(而不僅僅是一個表)。 select from (join subquery) unpivot...

當然,你可以改變表中的列名(到j_test_1,f_test_1等),但這可能太麻煩了。如果你這樣做,這兩個表中的id列名仍應該是相同的,並且您仍然需要using(id)語法。

1

問題是兩個表的列名是相同的,如果您嘗試在UNPIVOT中使用別名,它會給出錯誤 - 簡單名稱預計爲

在Oracle 12c中+,使用OUTER APPLY

select j.id, x.* 
    from scores_jan j 
    join scores_feb f 
    on j.id = f.id 
outer apply (
    select 'test_1' test_name, j.test_1 jan_score, f.test_1 feb_score from dual union all 
    select 'test_2', j.test_2, f.test_2 from dual union all 
    select 'test_3', j.test_3, f.test_3 from dual 
) x 

爲了版本,做子查詢的加盟,做走樣,然後用UNPIVOT

select * 
from (  
    select 
     j.id, 
     j.test_1 j_test_1, 
     j.test_2 j_test_2, 
     j.test_3 j_test_3, 
     f.test_1 f_test_1, 
     f.test_2 f_test_2, 
     f.test_3 f_test_3 
    from scores_jan j 
    join scores_feb f 
     on j.id = f.id 
    ) 
unpivot (
    (jan_score, feb_score) 
    for test_name in (
     (j_test_1, f_test_1) as 'test_1', 
     (j_test_2, f_test_2) as 'test_2', 
     (j_test_3, f_test_3) as 'test_3' 
    ) 
); 
0

附:

也可以解決這樣

select  id,test,jan_score,feb_score 

from    scores_jan j 
      join (select id as fid,test_1 as f1,test_2 as f2,test_3 as f3 
        from scores_feb 
        ) f 
      on  j.id = f.fid 
      unpivot ((jan_score,feb_score) for (test) in 
       ((test_1,f1) as 'test_1',(test_2,f2) as 'test_2',(test_3,f3) as 'test_3')) u 

order by test   
相關問題