如何将此混合行/列表转换为所需的输出。(Oracle SQL/Release:Ora12c)
我有这个Excel输入文件被远程传递,并试图导入到这个最终结果,没有任何运气。如有任何帮助/建议,将不胜感激。到目前为止,我已经尝试了Oracle LEAD函数来获取要透视的前6行(如果在本例中这是正确的术语的话),其余的都有问题 因此,我输入的数据是这种格式的(我在第4列末尾添加了行号,以使我的LEAD函数工作) 我想让它成为这种输出格式如何将此混合行/列表转换为所需的输出。(Oracle SQL/Release:Ora12c),sql,oracle,pivot,Sql,Oracle,Pivot,我有这个Excel输入文件被远程传递,并试图导入到这个最终结果,没有任何运气。如有任何帮助/建议,将不胜感激。到目前为止,我已经尝试了Oracle LEAD函数来获取要透视的前6行(如果在本例中这是正确的术语的话),其余的都有问题 因此,我输入的数据是这种格式的(我在第4列末尾添加了行号,以使我的LEAD函数工作) 我想让它成为这种输出格式 +------+------+------+--------+--------+------+------+--------------+-------+
+------+------+------+--------+--------+------+------+--------------+-------+
| Col1 | Col2 | Col3 | Col4 | Col5 | Col6 | Col7 | Col8 | Col9 |
+------+------+------+--------+--------+------+------+--------------+-------+
| 2019 | ABC | xyz | 112233 | 555666 | C | 1000 | blahblahblah | $1000 |
| 2019 | ABC | xyz | 112233 | 555666 | C | 1001 | blahblahxxyy | $999 |
| 2019 | ABC | xyz | 112233 | 555666 | C | 1029 | blahblahxxyy | $7676 |
| ... | ... | ... | ... | ... | . | ... | ... | ... |
| 2019 | EFG | xyz | 112233 | 555888 | C | 1000 | blahblahblah | $4440 |
| 2019 | EFG | xyz | 112233 | 555888 | C | 1001 | blahblahxxyy | $3875 |
| 2019 | EFG | xyz | 112233 | 555888 | C | 1029 | blahblahxxyy | $5029 |
| ... | ... | ... | ... | ... | . | ... | ... | ... |
+------+------+------+--------+--------+------+------+--------------+-------+
基本上,我需要将前6行(如果愿意的话,标题行)转换为它们下面的行号的水平/重复值。然后在n上重复逻辑,因为这些标题部分一直在重复,下面是行号表
感谢您的指点/帮助
注:这是我迄今为止一直在尝试/想出的方法
select (CASE WHEN Col1 = 'FYear' THEN Col2 END) New_Col1,
LEAD((CASE WHEN Col1 = 'Office' THEN Col2 END)) OVER (ORDER BY Col4) New_Col2,
LEAD((CASE WHEN Col1 = 'Org' THEN Col2 END),2,0) OVER (ORDER BY Col4) New_Col3,
LEAD((CASE WHEN Col1 = 'Acct' THEN Col2 END),3,0) OVER (ORDER BY Col4) New_Col4,
LEAD((CASE WHEN Col1 = 'SubAcct' THEN Col2 END),4,0) OVER (ORDER BY Col4) New_Col5,
LEAD((CASE WHEN Col1 = 'Status' THEN Col2 END),5,0) OVER (ORDER BY Col4) New_Col6
from demo_table
where col4 <7;
select(Col1='FYear'然后Col2 END时的情况)New_Col1,
在(Col4订购)新的Col2上引入(Col1=办公室然后Col2结束时的情况),
领先(Col1='Org'然后Col2 END时的情况),2,0)超过(Col4订单)新的Col3,
领先((Col1='Acct'然后Col2 END时的情况),3,0)超过(Col4订单)新的Col4,
领先(Col1=子CCT后Col2结束时的情况),4,0)超过(按Col4排序)新的Col5,
领先(Col1=状态后Col2结束时的情况),5,0)超过(Col4订单)新的Col6
从demo_表
其中,col4根据col4除以9,将“传统”旋转的第1-6行与每个行号的第“1000”、“1001”、“1029”行连接起来:
with
d as (select t.*, floor((col4 - 1) / 9) + 1 rn from t),
a as (select rn,
max(case col1 when 'FYear' then col2 end) col1,
max(case col1 when 'Office' then col2 end) col2,
max(case col1 when 'Org' then col2 end) col3,
max(case col1 when 'Acct' then col2 end) col4,
max(case col1 when 'SubAcct' then col2 end) col5,
max(case col1 when 'Status' then col2 end) col6
from d group by rn),
b as (select rn, col1 as col7, col2 as col8, col3 as col9
from d where col1 in ('1000', '1001', '1029'))
select *
from a join b using (rn)
order by rn, col7
根据col4除以9,将每个行号的“传统”枢轴行1-6与行“1000”、“1001”、“1029”连接起来:
with
d as (select t.*, floor((col4 - 1) / 9) + 1 rn from t),
a as (select rn,
max(case col1 when 'FYear' then col2 end) col1,
max(case col1 when 'Office' then col2 end) col2,
max(case col1 when 'Org' then col2 end) col3,
max(case col1 when 'Acct' then col2 end) col4,
max(case col1 when 'SubAcct' then col2 end) col5,
max(case col1 when 'Status' then col2 end) col6
from d group by rn),
b as (select rn, col1 as col7, col2 as col8, col3 as col9
from d where col1 in ('1000', '1001', '1029'))
select *
from a join b using (rn)
order by rn, col7
我支持行在DB中没有排序的评论。
此外,您不需要指定段的行数是否可以超过9行
我有一个解决方案,它适用于任何数量的行pr段,如果以某种方式保留顺序,它需要每个段在col1中以“FYear”开头,并且为了保留顺序,但不关心头行之后是否正好有三行
设置:
create table testtbl
(
col1 varchar2(100)
,col2 varchar2(100)
,col3 varchar2(100)
,col4 int
)
insert into testtbl values ('FYear' ,2019,'',1);
insert into testtbl values ('Office' ,'ABC','',2);
insert into testtbl values ('Org' ,'xyz','',3);
insert into testtbl values ('Acct' ,11122233,'',4);
insert into testtbl values ('SubAcct',555666,'',5);
insert into testtbl values ('Status' ,'C','',6);
insert into testtbl values (1000 ,'blahblahblah',1000,7);
insert into testtbl values (1001 ,'blahblahxxyy',999,8);
insert into testtbl values (1029 ,'blahblahxxyy',7676,9);
insert into testtbl values ('FYear' ,2019,'',10);
insert into testtbl values ('Office' ,'EFG','',11);
insert into testtbl values ('Org' ,'xyz','',12);
insert into testtbl values ('Acct' ,11122233,'',13);
insert into testtbl values ('SubAcct',555888,'',14);
insert into testtbl values ('Status' ,'C','',15);
insert into testtbl values (1000 ,'blahblahblah',4440,16);
insert into testtbl values (1001 ,'blahblahxxyy',3875,17);
insert into testtbl values (1029 ,'blahblahxxyy',5029,18);
解决方案:
我首先创建一个grp,它跨越序列中的所有行,然后在该组中找到标题值并将它们放在前6列中。然后,我将原来的3列添加为col7-9,最后过滤掉包含标题的行
select
col1,col2,col3,col4,col5,col6,col7,col8,col9
from
(
select
max(case when col1='FYear' then Col2 else '' end) over (partition by grp) Col1
,max(case when col1='Office' then Col2 else '' end) over (partition by grp) Col2
,max(case when col1='Org' then Col2 else '' end) over (partition by grp) Col3
,max(case when col1='Acct' then Col2 else '' end) over (partition by grp) Col4
,max(case when col1='SubAcct' then Col2 else '' end) over (partition by grp) Col5
,max(case when col1='Status' then Col2 else '' end) over (partition by grp) Col6
, col1 col7
, col2 col8
, col3 col9
from
(
select
col1,col2,col3,col4
,sum(case when col1='FYear' then 1 else 0 end ) over (order by col4) grp
from testtbl t
) a
) b
where col7 not in('FYear','Office','Org','Acct','SubAcct','Status' )
我支持在DB中没有对行排序的注释。
此外,您不需要指定段的行数是否可以超过9行
我有一个解决方案,它适用于任何数量的行pr段,如果以某种方式保留顺序,它需要每个段在col1中以“FYear”开头,并且为了保留顺序,但不关心头行之后是否正好有三行
设置:
create table testtbl
(
col1 varchar2(100)
,col2 varchar2(100)
,col3 varchar2(100)
,col4 int
)
insert into testtbl values ('FYear' ,2019,'',1);
insert into testtbl values ('Office' ,'ABC','',2);
insert into testtbl values ('Org' ,'xyz','',3);
insert into testtbl values ('Acct' ,11122233,'',4);
insert into testtbl values ('SubAcct',555666,'',5);
insert into testtbl values ('Status' ,'C','',6);
insert into testtbl values (1000 ,'blahblahblah',1000,7);
insert into testtbl values (1001 ,'blahblahxxyy',999,8);
insert into testtbl values (1029 ,'blahblahxxyy',7676,9);
insert into testtbl values ('FYear' ,2019,'',10);
insert into testtbl values ('Office' ,'EFG','',11);
insert into testtbl values ('Org' ,'xyz','',12);
insert into testtbl values ('Acct' ,11122233,'',13);
insert into testtbl values ('SubAcct',555888,'',14);
insert into testtbl values ('Status' ,'C','',15);
insert into testtbl values (1000 ,'blahblahblah',4440,16);
insert into testtbl values (1001 ,'blahblahxxyy',3875,17);
insert into testtbl values (1029 ,'blahblahxxyy',5029,18);
解决方案:
我首先创建一个grp,它跨越序列中的所有行,然后在该组中找到标题值并将它们放在前6列中。然后,我将原来的3列添加为col7-9,最后过滤掉包含标题的行
select
col1,col2,col3,col4,col5,col6,col7,col8,col9
from
(
select
max(case when col1='FYear' then Col2 else '' end) over (partition by grp) Col1
,max(case when col1='Office' then Col2 else '' end) over (partition by grp) Col2
,max(case when col1='Org' then Col2 else '' end) over (partition by grp) Col3
,max(case when col1='Acct' then Col2 else '' end) over (partition by grp) Col4
,max(case when col1='SubAcct' then Col2 else '' end) over (partition by grp) Col5
,max(case when col1='Status' then Col2 else '' end) over (partition by grp) Col6
, col1 col7
, col2 col8
, col3 col9
from
(
select
col1,col2,col3,col4
,sum(case when col1='FYear' then 1 else 0 end ) over (order by col4) grp
from testtbl t
) a
) b
where col7 not in('FYear','Office','Org','Acct','SubAcct','Status' )
由于您使用的是Oracle 12,因此可以利用match\u recognize
,这将快速解决此问题。(在Oracle 11中,您可以使用联接和旋转,如Plnder Stibbons所示,但这会更慢。)
请注意,我为输出中的前六列提供了更有意义的名称;对于最后三列,您应该找到比col7、col8、col9更好的名称。我还将fyear
、acct
和subacct
转换为number数据类型,这是您可能需要的。我允许col1
中的“已旋转”值(如'1000'
等)为除六个特殊值'FYear',Office'
等以外的任何值(包括该值有时可能为null
)-这可以从match\u recognize
的define
子句中分类为“x”的行的定义中看出
通过您的输入数据,我得到以下输出:
FYEAR OFFICE ORG ACCT SUBACCT STATUS COL7 COL8 COL9
----- ------ --- -------- ------- ------ ---- ------------ -----
2019 ABC xyz 11122233 555666 C 1000 blahblahblah $1000
2019 ABC xyz 11122233 555666 C 1001 blahblahxxyy $999
2019 ABC xyz 11122233 555666 C 1029 blahblahxxyy $7676
2019 EFG xyz 11122233 555888 C 1000 blahblahblah $4440
2019 EFG xyz 11122233 555888 C 1001 blahblahxxyy $3875
2019 EFG xyz 11122233 555888 C 1029 blahblahxxyy $5029
您可能还应该将col9
转换为数字;我没有表现出来,因为这取决于你真正拥有什么。它总是null
还是美元值(前面有美元符号的数字)?不管怎样,这是一个与你的问题无关的问题,但是请考虑一下。
另一个重要的注意事项:我假设您的“段”总是将前六行作为“特殊”行,精确的值在col1
中,正如您在示例中显示的那样。剩余的行可以有col1
中的任何内容(特殊值除外),并且这些行的数量可以是任何内容,包括无,在这种情况下,相应的“段”将在输出中产生绝对无任何内容。如果在这种特殊情况下需要不同的处理方式,可以很容易地适应,您只需解释该处理方式是什么。由于您使用的是Oracle 12,您可以利用匹配识别
,这将快速解决此问题。(在Oracle 11中,您可以使用联接和旋转,如Plnder Stibbons所示,但这会更慢。)
请注意,我为输出中的前六列提供了更有意义的名称;对于最后三列,您应该找到比col7、col8、col9更好的名称。我还将fyear
、acct
和subacct
转换为number数据类型,这是您可能需要的。我允许col1
中的“已旋转”值(如'1000'
等)是除六个特殊值'FYear'、'Office'
等以外的任何值(包括该值有时可能为null
)-这在分类为'