我想将所有行翻转为列。所以如果有以下5列 有3个数据行
ACCT_ID NAME PHONE MOBILE ALTERNATIVE_NAME
01 JOE BROWN 0456-9992-6666 07767828432 ZOE BROWN
02 GILL SHARP 0456-9992-6666 07763928432 BILL SHARP
03 ZAC LOWE 0236-9992-5644 07663925672 LUKE LOWE
我希望结果集如下所示。所以有3列5行。
仅添加了COL标题(COL1-COL3)以使内容更清晰,我不需要 列标题
COL1 COL2 COL3
01 02 03
JOE BROWN GILL SHARP ZAC LOWE
0456-9992-6666 0456-9992-6666 0236-9992-5644
07767828432 07763928432 07663925672
ZOE BROWN BILL SHARP LUKE LOWE
如果知道acct_id,以下SQL将起作用。但是我不知道acct_id,因此需要编写一些动态sql从表REPORTER.TEMP_PSR_REGION中选择acct_id,然后执行数据透视/取消数据透视。
CREATE TABLE REPORTER.TEMP_PSR_REGION
(
ACCT_ID VARCHAR(50) NOT NULL,
NAME VARCHAR(50) NOT NULL,
PHONE VARCHAR(50) NOT NULL,
MOBILE VARCHAR(50) NOT NULL,
ALTERNATIVE_CONTACT VARCHAR(50) NOT NULL
)
INSERT INTO TEMP_PSR_REGION
(ACCT_ID,
NAME,
PHONE,
MOBILE,
ALTERNATIVE_CONTACT)
VALUES ('01',
'JOE BROWN',
'0456-9992-6666',
'07767828432',
'ZOE BROWN')
INSERT INTO TEMP_PSR_REGION
(ACCT_ID,
NAME,
PHONE,
MOBILE,
ALTERNATIVE_CONTACT)
VALUES ('02',
'GILL SHARP',
'0456-9992-6666',
'07763928432',
'BILL SHARP')
INSERT INTO TEMP_PSR_REGION
(ACCT_ID,
NAME,
PHONE,
MOBILE,
ALTERNATIVE_CONTACT)
VALUES ('03',
'ZAC LOWE',
'0236-9992-5644',
'07663925672',
'LUKE LOWE')
--- PIVOT/UNPIVOT Example
select col1, col2, col3
from (
select t.*, t.acct_id as col_id
from TEMP_PSR_REGION t
)
unpivot
(
value FOR heading in (acct_id, name, phone, mobile, ALTERNATIVE_CONTACT)
)
pivot
(
max(value) for col_id in ('01' as col1, '02' as col2, '03' as col3)
)
order by case heading
when 'ACCT_ID' then 1
when 'NAME' then 2
when 'PHONE' then 3
when 'MOBILE' then 4
when 'ALTERNATIVE_CONTACT' then 5
end
动态sql会执行以下操作。我以前没有写过动态sql吗?
答案 0 :(得分:0)
您可以通过查询获取枢轴的IN
子句:
select listagg('''' || acct_id || ''' as col' || rownum, ', ') within group (order by acct_id)
from TEMP_PSR_REGION;
LISTAGG(''''||ACCT_ID||'''ASCOL'||ROWNUM,',')WITHINGROUP(ORDERBYACCT_ID)
------------------------------------------------------------------------
'01' as col1, '02' as col2, '03' as col3
然后可以将其用作查询的一部分以生成动态SQL语句,然后将该语句作为ref游标打开。在此示例中,我使用一个SQL * Plus(或SQL Developer或SQLcl)客户端refcursor
变量来简化如何声明和播放它:
var rc refcursor
declare
l_sql varchar2(32767);
begin
select
q'[
select *
from (
select t.*, t.acct_id as col_id
from TEMP_PSR_REGION t
)
unpivot
(
value FOR heading in (acct_id, name, phone, mobile, ALTERNATIVE_CONTACT)
)
pivot
(
max(value) for col_id in (]'
|| listagg('''' || acct_id || ''' as col' || rownum, ', ') within group (order by acct_id)
|| q'[)
)
order by case heading
when 'ACCT_ID' then 1
when 'NAME' then 2
when 'PHONE' then 3
when 'MOBILE' then 4
when 'ALTERNATIVE_CONTACT' then 5
end]'
into l_sql
from TEMP_PSR_REGION;
dbms_output.put_line(l_sql); -- for debugging only
open :rc for l_sql;
end;
/
其中大部分是您的原始查询。本质上,它将查询放入字符串变量中,但是会发生变化
select col1, col2, col3
from (
...
到
q'[
select *
from (
...]'
尽管您可以根据需要使用另一个listagg()
生成该选择列表;更重要的是:
...
pivot
(
max(value) for col_id in ('01' as col1, '02' as col2, '03' as col3)
)
...
收件人:
q'[...
pivot
(
max(value) for col_id in (]'
|| listagg('''' || acct_id || ''' as col' || rownum, ', ') within group (order by acct_id)
|| q'[)
)
...]'
执行该块时,dbms_output
调试会显示生成的语句,该语句与对listagg()
求值后的原始语句相同:
select *
from (
select t.*, t.acct_id as col_id
from TEMP_PSR_REGION t
)
unpivot
(
value FOR heading in (acct_id, name, phone, mobile, ALTERNATIVE_CONTACT)
)
pivot
(
max(value) for col_id in ('01' as col1, '02' as col2, '03' as col3)
)
order by case heading
when 'ACCT_ID' then 1
when 'NAME' then 2
when 'PHONE' then 3
when 'MOBILE' then 4
when 'ALTERNATIVE_CONTACT' then 5
end
PL/SQL procedure successfully completed.
您可以显示打开的参考光标:
print rc
COL1 COL2 COL3
-------------------------------------------------- -------------------------------------------------- --------------------------------------------------
01 02 03
JOE BROWN GILL SHARP ZAC LOWE
0456-9992-6666 0456-9992-6666 0236-9992-5644
07767828432 07763928432 07663925672
ZOE BROWN BILL SHARP LUKE LOWE
使用rownum
有点晦涩难懂,因为标题可能乱七八糟(因为没有排序顺序),但是似乎您根本不在乎这些。如果确实如此,则可以使用子查询为基表中的每一行分配一个数字索引,然后使用该值代替rownum
。
您可能会将其放在返回ref游标的函数中,但这取决于您如何调用它并使用结果。 var
和print
只是一个演示,可能不是您真正使用的。
您可能还需要考虑让报告层(如果有的话)处理数据透视。