我无法在两个表之间取消连接的结果。这两个表定义为:
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
如果我在没有指定我感兴趣的列的情况下编写unpivot,它看起来像这样:
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:此处只允许使用简单的列名
有没有办法让这个univot工作?我可以将其中一个表放入子查询中,但使用子查询只是为了更改列的别名似乎非常不理想。
答案 0 :(得分: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 |
+----+--------+-----------+-----------+
答案 1 :(得分: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)
语法。
答案 2 :(得分: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'
)
);
答案 3 :(得分:0)
我不会想到" univot"是正确的方法。如果每个表中每个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 ;
您还应该认识到,在不同的月份使用单独的表是一个非常糟糕的想法。您应该将所有数据存储在一个表中,并使用指定月份的列。
答案 4 :(得分:0)
P.S。
也可以像这样解决
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