取消透视到 Oracle 中的多个列

Posted

技术标签:

【中文标题】取消透视到 Oracle 中的多个列【英文标题】:Unpivoting into multiple columns in Oracle 【发布时间】:2020-06-30 16:05:16 【问题描述】:

我有一张如下表:

EVENT_ID    NUM_A    NUM_A_SRC    NUM_B    NUM_B_SRC
1           5        Yelp         4        Google
2           3        Yelp         1        Google

我需要把它变成以下格式:

EVENT_ID    SRC       RANK
1           Yelp      5
1           Google    4
2           Yelp      3
2           Google    1

我终其一生都无法弄清楚如何取消透视并将结果集设置为多列。任何人都可以帮忙吗?请参阅下面的可重现示例:

CREATE TABLE EXAMPLE(
EVENT_ID NUMBER,
NUM_A NUMBER,
NUM_A_SRC VARCHAR2(10),
NUM_B NUMBER,
NUM_B_SRC VARCHAR2(10)
); 

INSERT INTO EXAMPLE (EVENT_ID, NUM_A, NUM_A_SRC, NUM_B, NUM_B_SRC)
VALUES
(1, 5, 'Yelp', 4, 'Google');

INSERT INTO EXAMPLE (EVENT_ID, NUM_A, NUM_A_SRC, NUM_B, NUM_B_SRC)
VALUES
(2, 3, 'Yelp', 1, 'Google');

SELECT * FROM EXAMPLE;

【问题讨论】:

【参考方案1】:

在Oracle中,最简单的方法大概是union all

select event_id, num_a_src src, num_a rnk from example
union all
select event_id, num_b_src, num_b from example

请注意,rank 是一个语言关键字(有一个以该名称命名的窗口函数) - 我在查询中将其重命名为 rnk

Demo on DB Fiddle

事件ID | SRC |核糖核酸 --------: | :----- | --: 1 |叫喊声| 5 2 |叫喊声| 3 1 |谷歌 | 4 2 |谷歌 | 1

【讨论】:

我不喜欢扫描源表两次而不是一次。【参考方案2】:

对源表进行一次扫描:

with s (event_id, num_a, num_a_src, num_b, num_b_src) as (
select 1, 5, 'Yelp', 4, 'Google' from dual union all
select 2, 3, 'Yelp', 1, 'Google' from dual)
select event_id,
decode(rn, 1, num_a    , 2, num_b    ) rank,
decode(rn, 1, num_a_src, 2, num_b_src) num_src
from s, (select rownum rn from dual connect by level <= 2)
order by rank desc;

  EVENT_ID       RANK NUM_SRC
---------- ---------- -------
         1          5 Yelp
         1          4 Google
         2          3 Yelp
         2          1 Google

【讨论】:

以上是关于取消透视到 Oracle 中的多个列的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 11g:取消透视多个列并包含列名

尝试在 Oracle SQL 中取消透视列时出错

在 MySQL 中取消透视多个列

取消透视表 Oracle 中的数据

取消透视多个列

如何取消透视多个列并从任一列中排除值?