sql - 行到列 - Oracle - 不使用联合 ALL
问题描述
除了使用 union all 之外,还有没有更好的方法来实现以下结果?该表有数百万条记录,因此寻找一个更好的选择,其中一次获取结果集。
create table test_tab (
rec_id number(3),
p_code varchar2(5),
q_code varchar2(5),
r_code varchar2(5),
p_amt number(8),
q_amt number(8),
r_amt number(8)
);
delete from test_tab;
insert into test_tab (rec_id, p_code, q_code,r_code , p_amt,q_amt,r_amt)
values (1, 'p1','q1','r1',18,9,9);
insert into test_tab (rec_id, p_code, q_code,r_code , p_amt,q_amt,r_amt)
values (2, 'p2','q2','r2',28,6,4);
insert into test_tab (rec_id, p_code, q_code,r_code , p_amt,q_amt,r_amt)
values (3, 'p1',null,null,18,null,null);
insert into test_tab (rec_id, p_code, q_code,r_code , p_amt,q_amt,r_amt)
values (4, null,'q3','r3',null,9,9);
commit;
select rec_id, p_code,p_amt from test_tab where p_code is not null
union all
select rec_id, q_code,q_amt from test_tab where q_code is not null
union all
select rec_id, r_code,r_amt from test_tab where r_code is not null;
结果:
REC_ID | P_CODE | P_AMT |
---|---|---|
1 | q1 | 9 |
1 | p1 | 18 |
1 | r1 | 9 |
2 | p2 | 28 |
2 | q2 | 6 |
2 | r2 | 4 |
3 | p1 | 18 |
4 | q3 | 9 |
4 | r3 | 9 |
解决方案
这是unpivot
运算符的基本应用程序,自 Oracle 11.1 起可用。
select rec_id, code, amt
from test_tab
unpivot ((code, amt) for ord in
((p_code, p_amt) as 1, (q_code, q_amt) as 2, (r_code, r_amt) as 3))
order by rec_id, ord -- if needed
;
REC_ID CODE AMT
---------- ----- ----------
1 p1 18
1 q1 9
1 r1 9
2 p2 28
2 q2 6
2 r2 4
3 p1 18
4 q3 9
4 r3 9
9 rows selected.
注意几件事。我称输出列code
和-在输出列名称中amt
包含前缀是没有意义的。p_
此外,“排除空值”是 中的默认值unpivot
,所以我不需要明确提及它(尽管它不会伤害任何东西)。最后,虽然可能并不重要,但我还创建了一个列ord
来反映列顺序,并按照与输入中的列相同的顺序对输出中的行进行排序。
推荐阅读
- rust - Actix-Web:每 10 秒运行一次服务
- python - 如何在python 3中用'->'分隔单词列表
- javascript - 为什么我无法通过 nuxtServerInit 获取会话数据?
- java - Mule Http 连接器提供 BufferInputStream ,它在转换时提供垃圾值
- java - 在 Java 中执行 Linux 命令时,缓冲区读取器添加“[?1034h”作为最后一行
- python - 根据 setup_module 或其他函数的输出动态参数化 pytest 测试函数
- laravel - 检查下一个运行 Laravel 的时间表是什么时候
- sql - SQL Server 选择列中的所有最大和最小数据
- delphi - TDBNavigator 背景透明度颜色错误
- python - 如何使用字典值中的精确字符串创建新列表?