簡體   English   中英

取消列名相同的兩個表之間的聯接

[英]sql - Unpivot a join between two tables with the same column names

我無法取消兩個表之間的聯接結果。 這兩個表定義為:

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;

我想取消此操作以獲取每個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:此處僅允許使用簡單的列名稱

有沒有辦法使這個樞紐起作用? 我可以將其中一個表放入子查詢中,但是使用子查詢僅用於更改列的別名似乎不太理想。

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        |
+----+--------+-----------+-----------+

如您所見,問題在於列名不明確。 確實有兩個問題。 一個是id列。 您可以使用其他連接語法來處理它-而不是on j.id = f.idusing(id) 如果您不熟悉此聯接語法,請查閱文檔。

但是,無法通過這種方式解決test_1列名稱的歧義,並且如您所見,您不能將表限定符與unpivot

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

當然,您可以將表中的列名更改(更改為j_test_1f_test_1等),但這可能會帶來太多麻煩。 如果采用這種方式,則兩個表中的id列名稱仍應相同,並且仍然需要using(id)語法。

問題在於兩個表的列名相同,並且如果您嘗試在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'
    )
);

我認為“無誤”是正確的方法。 如果每個表中的每個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 ;

您還應該認識到,在單獨的月份中使用單獨的表確實是個主意。 您應該將所有數據存儲在一個表中,並在其中指定月份。

聚苯乙烯

也可以這樣解決

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         

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM