oracle动态行转不定列
oracle中如何进行行转列,Oracle中的行转列例子详解

oracle中如何进⾏⾏转列,Oracle中的⾏转列例⼦详解--场景1:A Ba1a2a3b4b5希望实现如下效果:a1,2,3b4,5create table tmp asselect 'a' A, 1 B from dual union allselect 'a' A, 2 B from dual union allselect 'a' A, 3 B from dual union allselect 'b' A, 4 B from dual union allselect 'b' A, 5 B fromdual;1.⽅法1:listagg--listagg() + group by: 推荐使⽤select a,listagg(b,',') within group (order by b) as c from tmp group bya;--listagg() + over(partition by )select distinct a,listagg(b,',') within group (order by b) over(partition by a) as c fromtmp ;2.wm_concatselecta,to_char(wm_concat(b)) as b from tmp group bya3.sys_connect_by_pathselect a, max(substr(sys_connect_by_path(b, ','), 2)) strfrom (select a, b, row_number() over(partition by a order by b) rn fromtmp)startwith rn = 1connectby rn = prior rn + 1and a =prior agroup bya;4.max+decodeselecta,max(decode(rn, 1, b, null)) ||max(decode(rn, 2, ',' || b, null)) ||max(decode(rn, 3, ',' || b, null)) strfrom (select a,b,row_number() over(partition by a order by b) as rn fromtmp)group byaorder by1;5.row_number()+leadselect a, strbfrom (selecta,row_number()over(partition by a order by b) asrn,b|| lead(',' || b, 1) over(partition by a order by b) ||lead(',' || b, 2) over(partition by a order by b) ||lead(',' || b, 3) over(partition by a order by b) as strfromtmp)where rn = 1order by 1;6.model语句select a, substr(str,2) bfromtmpmodelreturn updated rows partition by(a) dimension by(row_number() over(partition by a order by b) asrn)measures(cast(b as varchar2(20)) as str)rules upsert iterate(3) until(presentv(str[iteration_number+2],1,0) = 0)(str[0] = str[0]||','||str[iteration_number + 1])order by 1;--场景2:no sex004 2002 2002 2003 1002 1希望实现如下效果:c1 c2002 1 2003 1 0004 0 1也就是说按no sex两个字段count⼈数,得到⼆维表。
Oracle行转列(使用pivot函数)

Oracle⾏转列(使⽤pivot函数)在⽇常使⽤中,经常遇到这样的情况,需要将数据库中⾏转化成列显⽰,如转化为这个时候,我们就需要使⽤pivot函数百度后,参考⽹址,完成了以下操作with temp as(select '四川省' nation ,'成都市' city,'第⼀' ranking from dual union allselect '四川省' nation ,'绵阳市' city,'第⼆' ranking from dual union allselect '四川省' nation ,'德阳市' city,'第三' ranking from dual union allselect '四川省' nation ,'宜宾市' city,'第四' ranking from dual union allselect '湖北省' nation ,'武汉市' city,'第⼀' ranking from dual union allselect '湖北省' nation ,'宜昌市' city,'第⼆' ranking from dual union allselect '湖北省' nation ,'襄阳市' city,'第三' ranking from dual)select * from (select nation,city,ranking from temp)pivot (max(city) for ranking in ('第⼀' as 第⼀,'第⼆' AS 第⼆,'第三' AS 第三,'第四' AS 第四));这样就顺利的实现了操作,其中关键函数pivot,其⽤法如下pivot(聚合函数 for 列名 in(类型))--其中 in(‘’) 中可以指定别名,in中还可以指定⼦查询,⽐如 select distinct ranking from temp当然也可以不使⽤pivot函数,使⽤下⾯的语句同样可以实现效果with temp as(select '四川省' nation ,'成都市' city,'第⼀' ranking from dual union allselect '四川省' nation ,'绵阳市' city,'第⼆' ranking from dual union allselect '四川省' nation ,'德阳市' city,'第三' ranking from dual union allselect '四川省' nation ,'宜宾市' city,'第四' ranking from dual union allselect '湖北省' nation ,'武汉市' city,'第⼀' ranking from dual union allselect '湖北省' nation ,'宜昌市' city,'第⼆' ranking from dual union allselect '湖北省' nation ,'襄阳市' city,'第三' ranking from dual)select nation,max(decode(ranking, '第⼀', city, '')) as 第⼀,max(decode(ranking, '第⼆', city, '')) as 第⼆,max(decode(ranking, '第三', city, '')) as 第三,max(decode(ranking, '第四', city, '')) as 第四from temp group by nation;当然Oracle还提供了unpivot函数,实现列转换的操作,项⽬中还没有使⽤,也就没有细细研究了。
ORACLE动态行转列实现

ORACLE 动态行转列实现项目开发中经常需要对表或视图的数据进行行转列的变换,在ORACLE 11G中有专门的函数处理,但在旧版本的ORACLE,需要自己处理,因此编写了一个存储过程来实现,输入指定的参数,返回行转列的游标。
一、字符串肢解函数Function f_Split_Str(p_Str Varchar2, p_Division Varchar2, p_Seq Int)Return Varchar2Isv_First Int;v_Last Int;BeginIf p_Seq < 1ThenReturn Null;End If;If p_Seq = 1ThenIf Instr(p_Str, p_Division, 1, p_Seq) = 0ThenReturn p_Str;ElseReturn Substr(p_Str, 1, Instr(p_Str, p_Division, 1) - 1);End If;Elsev_First := Instr(p_Str, p_Division, 1, p_Seq - 1);v_Last := Instr(p_Str, p_Division, 1, p_Seq);If (v_Last = 0) ThenIf (v_First > 0) ThenReturn Substr(p_Str, v_First + 1);ElseReturn Null;End If;ElseReturn Substr(p_Str, v_First + 1, v_Last - v_First - 1);End If;End If;End f_Split_Str;二、带计算结果的动态行转列过程实现。
--带计算的行转列过程Procedure R2c_Cac(p_Tablename In Varchar2, --表名p_Keep_Cols In Varchar2, --保持列,多个用逗号分隔p_Pivot_Col In Varchar2, --翻转列,查询表里面的可能出现的内容组成p_Pivot_Val In Varchar2, --计算列p_Where In Varchar2Default Null, --条件选择带WHEREp_Func In Varchar2Default'max', --计算函数p_Frozen_Pivot_Cols In Varchar2, --固定选择翻转列值p_Frozen_Pivot_Cols_Disp In Varchar2, --对应的显示列值t_Rec Out Sys_Refcursor) Is --游标返回v_Sql Varchar2(8000);Type v_Keep_Ind_By Is Table Of Varchar2(4000) Index By Binary_Integer;v_Keep v_Keep_Ind_By;--Type v_Pivot_Ind_By Is Table Of Varchar2(4000) Index By Binary_Integer;v_Pivot v_Pivot_Ind_By;v_Keep_Cnt Int;---Type v_Frozen_Pivot_Ind_By Is Table Of Varchar2(4000) Index By Binary_Integer;v_Frozen_Pivot v_Frozen_Pivot_Ind_By;--Type v_Frozen_Pivot_Disp_Ind_By Is Table Of Varchar2(4000) Index By Binary_Integer;v_Frozen_Pivot_Disp v_Frozen_Pivot_Disp_Ind_By;v_Frozen_Cnt Int;--v_Group_By Varchar2(4000);Begin--计算保持列的个数v_Keep_Cnt := Length(p_Keep_Cols) - Length(Replace(p_Keep_Cols, ',')) + 1;--把保持列放入数组For i In1 .. v_Keep_Cnt Loopv_Keep(i) := f_Split_Str(p_Keep_Cols, ',', i);End Loop;If p_Frozen_Pivot_Cols Is Not Null Then--计算固定翻转列的个数v_Frozen_Cnt := Length(p_Frozen_Pivot_Cols) -Length(Replace(p_Frozen_Pivot_Cols, ',')) + 1;--把固定翻转列放入数组For i In1 .. v_Frozen_Cnt Loopv_Frozen_Pivot(i) := f_Split_Str(p_Frozen_Pivot_Cols, ',', i);End Loop;--计算固定翻转列显示的个数v_Frozen_Cnt := Length(p_Frozen_Pivot_Cols_Disp) -Length(Replace(p_Frozen_Pivot_Cols_Disp, ',')) + 1;--把固定翻转列显示放入数组For i In1 .. v_Frozen_Cnt Loopv_Frozen_Pivot_Disp(i) := f_Split_Str(p_Frozen_Pivot_Cols_Disp, ',', i);End Loop;If v_Frozen_Pivot_Disp.Count <> v_Frozen_Pivot.Count ThenRaise Ex;End If;Else--把传入的翻转列变成表变量里面,翻转列中可能出现的值,到时候查询出来的时候按GROUP BY 顺序出现v_Sql := 'select ' || 'cast(' || p_Pivot_Col ||' as varchar2(200)) as ' || p_Pivot_Col || ' from ' ||p_Tablename || ' group by ' || p_Pivot_Col;Execute Immediate v_Sql Bulk CollectInto v_Pivot;End If;----------根据保持列求出GROUP BY 表达式For i In1 .. v_Keep.Count Loopv_Group_By := v_Group_By || v_Keep(i) || ',';End Loop;v_Group_By := Rtrim(v_Group_By, ',');-------v_Sql := 'select ' || v_Group_By || ',';--If p_Frozen_Pivot_Cols Is Not Null Then--固定翻转列列出For x In1 .. v_Frozen_Pivot.Count Loopv_Sql := v_Sql || ' ' || p_Func || '(decode(' || p_Pivot_Col || ',' ||Chr(39) || v_Frozen_Pivot(x) || Chr(39) || ',' ||p_Pivot_Val || ',null)) as "' || v_Frozen_Pivot_Disp(x) || '",';End Loop;Else--从数据库里面查询内容列出For x In1 .. v_Pivot.Count Loopv_Sql := v_Sql || ' ' || p_Func || '(decode(' || p_Pivot_Col || ',' ||Chr(39) || v_Pivot(x) || Chr(39) || ',' || p_Pivot_Val ||',null)) as "' || v_Pivot(x) || '",';End Loop;End If;v_Sql := Rtrim(v_Sql, ',');----是否有条件选择刷新数据If p_Where Is Not Null Thenv_Sql := v_Sql || ' from ' || p_Tablename || ' ' || p_Where ||' group by ' || v_Group_By;Elsev_Sql := v_Sql || ' from ' || p_Tablename || ' group by ' ||v_Group_By;End If;--打印SQLp_Print_Sql(v_Sql);--Dbms_Output.Put_Line(v_Sql);Open t_Rec For v_Sql;ExceptionWhen Others ThenRaise;Open t_Rec ForSelect'异常'From Dual Where0 = 1;End;。
oracle的行转列函数

oracle的行转列函数Oracle是一种现代化、高效的数据库管理系统,它在行列转换方面有着强大的转换函数和工具。
行列转换函数是Oracle数据库中的一个重要组成部分,它可以用来将行数据转换为列数据,或将列数据转换为行数据,这在业务分析、数据挖掘等方面都有着极大的用处。
本文将简要介绍Oracle中的行列转换函数。
1. UNPIVOT函数UNPIVOT函数可以将一张带有多个列的表,转换为只有两列的表,其中一列是原来表格的列名,另一列是原来表格这一列的值。
UNPIVOT函数的语法如下:```SELECT *FROM table_name UNPIVOT((value1, 'column1') FOR column1 IN (column2, column3, ...),(value2, 'column2') FOR column2 IN (column3, column4, ...),...);```其中,table_name代表要转换的表格的名称,columnX代表原表格中的列名,valueX代表原表格中的值。
例如,若原表格中有A、B、C、D四个列,包含多行数据,那么可以使用以下语句将其转换为只有两列的表:该语句将生成两列,一列为name,包含了A、B、C、D四个列的名称,另一列为value,包含了相应列的值。
这样就可以方便地进行数据分析了。
该语句将生成一列key,表示原表格中的唯一关键字列,另外还有A、B、C三列,表示原表格中包含的三个列,每行记录表示一个唯一的key值和对应的A、B、C三个列的值。
3. CROSS JOIN函数CROSS JOIN函数可以将两个表中的每一个记录都做一个笛卡尔积,生成一个新表。
例如,若有两个表T1和T2,T1有列A、B,T2有列C、D,可以使用以下语句将它们进行笛卡尔积,生成一个新表:```SELECT *FROM T1CROSS JOIN T2;```该语句将生成一个新表,包含了所有T1和T2中的记录的笛卡尔积。
oracle动态实现行转列操作

oracle动态实现⾏转列操作--⽤到,case when语句,以及listagg--整个流程控制语句declaretxtsqlcostitem varchar(8000); --case when ⾏转列语句selectsqltxtcostitem varchar(8000); --case when ⾏转列语句后查询字段txtsqlcostitemex varchar(8000); --case when ⾏转列语句exselectsqltxtcostitemex varchar(8000); --case when ⾏转列语句后查询字段exselectsqltxt varchar(8000); --定义查询字段变量sqltxtcostitem varchar(8000); --整个⼦查询语句beginselect listagg('sum(nvl(case when materialofcostid= '''||to_char(materialofcostid) ||''' then TspTaskVendorApportItems.vtaxinvalue end,0)) as vtaxinvalue'||to_char(MaterialCode),',') within group(order by materialofcostid, MaterialCode) costitemvalue,listagg('vtaxinvalue'|| to_char(MaterialCode), ',') within group(order by materialofcostid, MaterialCode) costitems,listagg('sum(nvl(case when materialofcostid= '''||to_char(materialofcostid) ||''' then TspTaskVendorApportItems.vtaxexvalue end,0)) as vtaxexvalue'||to_char(MaterialCode),',') within group(order by materialofcostid, MaterialCode) costitemvalue,listagg('vtaxexvalue'|| to_char(MaterialCode), ',') within group(order by materialofcostid, MaterialCode) costitemsinto txtsqlcostitem,selectsqltxtcostitem,txtsqlcostitemex,selectsqltxtcostitemex --赋值变量from (select TspTaskVendorApportItems.materialofcostid,materials.MaterialCodefrom TspTaskVendorApportItemsinner join materialson TspTaskVendorApportItems.materialofcostid =materials.MaterialIDgroup by TspTaskVendorApportItems.materialofcostid,materials.MaterialCode);sqltxtcostitem :='';selectsqltxt :='';-- IF (trim(txtsqlcostitem) is not null)IF (length(trim(txtsqlcostitem)) >0) --判断流程语句thensqltxtcostitem :=' select TspTaskMatItems.TaskBillID,TspTaskMatItems.MaterialID,TspTaskMatItems.MatItemID , '||txtsqlcostitem ||','|| txtsqlcostitemex ||'from TspTaskBills inner join TspTaskMatItems on TspTaskBills.TaskBillID=TspTaskMatItems.TaskBillID inner join TspTaskVendorApportItemson TspTaskMatItems.TaskBillID =TspTaskVendorApportItems.TaskBillID andTspTaskMatItems.MaterialID=TspTaskVendorApportItems.MaterialID andTspTaskVendorApportItems.MatItemID =TspTaskMatItems.MatItemIDgroup by TspTaskMatItems.TaskBillID,TspTaskMatItems.MaterialID,TspTaskMatItems.MatItemID ';selectsqltxt :=','|| selectsqltxtcostitem ||','||selectsqltxtcostitemex;end if;dbms_output.put_line(sqltxtcostitem); --打印⼦查询语句dbms_output.put_line(selectsqltxt); --查询字段end;⽤到的表结构可以⾃⾏根据语句的⾥内容⾃⾏创建。
oracle行转列(动态行转不定列)

oracle⾏转列(动态⾏转不定列)/*物料需要数量需要仓库现存量仓库现存量仓库数量批次A1 2 C1 C1 20 123A1 2 C1 C2 30 111A1 2 C1 C2 20 222A1 2 C1 C3 10 211A2 3 C4 C1 40 321A2 3 C4 C4 50 222A2 3 C4 C4 60 333A2 3 C4 C5 70 223我需要把上⾯的查询结果转换为下⾯的。
物料需要数量需要仓库 C1 C2 C3 C4 C5A1 2 C1 20 50 10 0 0A2 3 C4 40 0 0 110 70*/---------------------------------------------------------------建表----------------判断表是否存在declare num number;beginselect count(1) into num from user_tables where table_name='TEST';if num>0 thenexecute immediate 'drop table TEST';end if;end;----------------建表CREATE TABLE TEST(WL VARCHAR2(10),XYSL INTEGER,XYCK VARCHAR2(10),XCLCK VARCHAR2(10),XCLCKSL INTEGER,PC INTEGER);----------------第⼀部分测试数据INSERT INTO TEST VALUES('A1', 2, 'C1', 'C1' , 20, 123);INSERT INTO TEST VALUES('A1', 2, 'C1', 'C2' , 30, 111);INSERT INTO TEST VALUES('A1', 2, 'C1', 'C2' , 20, 222);INSERT INTO TEST VALUES('A1', 2, 'C1', 'C3' , 10, 211);INSERT INTO TEST VALUES('A2', 3, 'C4', 'C1' , 40, 321);INSERT INTO TEST VALUES('A2', 3, 'C4', 'C4' , 50, 222);INSERT INTO TEST VALUES('A2', 3, 'C4', 'C4' , 60, 333);INSERT INTO TEST VALUES('A2', 3, 'C4', 'C5' , 70, 223);COMMIT;--select * from test;---------------------------------------------------------------⾏转列的存储过程CREATE OR REPLACE PROCEDURE P_TEST ISV_SQL VARCHAR2(2000);CURSOR CURSOR_1 IS SELECT DISTINCT T.XCLCK FROM TEST T ORDER BY XCLCK;BEGINV_SQL := 'SELECT WL,XYSL,XYCK';FOR V_XCLCK IN CURSOR_1LOOPV_SQL := V_SQL || ',' || 'SUM(DECODE(XCLCK,''' || V_XCLCK.XCLCK ||''',XCLCKSL,0)) AS ' || V_XCLCK.XCLCK;END LOOP;V_SQL := V_SQL || ' FROM TEST GROUP BY WL,XYSL,XYCK ORDER BY WL,XYSL,XYCK';--DBMS_OUTPUT.PUT_LINE(V_SQL);V_SQL := 'CREATE OR REPLACE VIEW RESULT AS '|| V_SQL;--DBMS_OUTPUT.PUT_LINE(V_SQL);EXECUTE IMMEDIATE V_SQL;END;----------------------------------------------------------------结果----------------执⾏存储过程,⽣成视图BEGINP_TEST;END;----------------结果SELECT * FROM RESULT T;WL XYSL XYCK C1 C2 C3 C4 C5---------- --------------------------------------- ---------- ---------- ---------- ---------- ---------- ----------A1 2 C1 20 50 10 0 0A2 3 C4 40 0 0 110 70 ----------------第⼆部分测试数据INSERT INTO TEST VALUES('A1', 2, 'C1', 'C6' , 20, 124);INSERT INTO TEST VALUES('A2', 2, 'C1', 'C7' , 30, 121);INSERT INTO TEST VALUES('A3', 2, 'C1', 'C8' , 20, 322);COMMIT;----------------报告存储过程,⽣成视图BEGINP_TEST;END;----------------结果SELECT * FROM RESULT T;WL XYSL XYCK C1 C2 C3 C4 C5 C6 C7 C8 ----- ----- -------- ------- -------- ---------- ---------- ---------- ---------- ---------- ----------A1 2 C1 20 50 10 0 0 20 0 0A2 2 C1 0 0 0 0 0 0 30 0A2 3 C4 40 0 0 110 70 0 0 0A3 2 C1 0 0 0 0 0 0 0 20--------------- 删除实体DROP VIEW RESULT;DROP PROCEDURE P_TEST;DROP TABLE TEST;。
oracle行转列,列转行函数的使用(listagg,xmlagg)

oracle⾏转列,列转⾏函数的使⽤(listagg,xmlagg)⼀、⾏转列listagg函数:场景:这⾥的表数据使⽤的是oracle默认的scott账户下的emp(员⼯)表。
规范写法 : LISTAGG(字段, 连接符) WITHIN GROUP (ORDER BY 字段)通常情况下,LISTAGG是满⾜需要的,LISTAGG 返回的是⼀个varchar2类型的数据,最⼤字节长度为4000。
所以,在实际开发中,我们可能会遇到⼀个问题,连接长度过长。
在这个时候,我们需要将LISTAGG函数改成XMLAGG函数。
XMLAGG返回的类型为CLOB,最⼤字节长度为32767。
LISTAGG例⼦:1、使⽤条件查询部门号为20号的员⼯:-- 查询部门为20的员⼯列表SELECT t.DEPTNO,t.ENAME FROM SCOTT.EMP t where t.DEPTNO ='20' ;2、使⽤listagg() WITH GROUP()将多⾏合并成⼀⾏(⽐较常⽤)SELECTT.DEPTNO,listagg (T.ENAME, ',') WITHIN GROUP (ORDER BY T.ENAME) namesFROMSCOTT.EMP TWHERET.DEPTNO ='20'GROUP BYT.DEPTNO3、使⽤listagg() width group() over将多⾏记录在⼀⾏显⽰(不常⽤)SELECTT .DEPTNO,listagg (T .ENAME, ',') WITHIN GROUP (ORDER BY T .ENAME) over(PARTITION BY T .DEPTNO)FROMSCOTT.EMP TWHERET .DEPTNO ='20'⼆、XMLAGG函数的例⼦:XMLAGG(XMLPARSE(CONTENT BSO.ID || ',' WELLFORMED) ORDER BY BSO.ID).GETCLOBVAL()规划写法: XMLAGG(XMLPARSE(CONTENT 字段 || 字符串 WELLFORMED) ORDER BY 字段).GETCLOBVAL()三、对于mysql相同的效果实现,可以使⽤group_concat() 函数,详情可参考:mysql相同效果的实现 https:///sinat_36257389/article/details/95052001PostgreSQL 相同效果的实现 https:///sinat_36257389/article/details/95611686转⾃:,转载请注明来源。
Oracle行列转换

Oracle⾏列转换⼀、建表与插⼊数据1.1、建表1 create table kecheng2 (3 id NUMBER,4 name VARCHAR2(20),5 course VARCHAR2(20),6 score NUMBER7 );8 insert into kecheng (id, name, course, score)9 values (1, '张三', '语⽂', 67);10 insert into kecheng (id, name, course, score)11 values (1, '张三', '数学', 76);12 insert into kecheng (id, name, course, score)13 values (1, '张三', '英语', 43);14 insert into kecheng (id, name, course, score)15 values (1, '张三', '历史', 56);16 insert into kecheng (id, name, course, score)17 values (1, '张三', '化学', 11);18 insert into kecheng (id, name, course, score)19 values (2, '李四', '语⽂', 54);20 insert into kecheng (id, name, course, score)21 values (2, '李四', '数学', 81);22 insert into kecheng (id, name, course, score)23 values (2, '李四', '英语', 64);24 insert into kecheng (id, name, course, score)25 values (2, '李四', '历史', 93);26 insert into kecheng (id, name, course, score)27 values (2, '李四', '化学', 27);28 insert into kecheng (id, name, course, score)29 values (3, '王五', '语⽂', 24);30 insert into kecheng (id, name, course, score)31 values (3, '王五', '数学', 25);32 insert into kecheng (id, name, course, score)33 values (3, '王五', '英语', 8);34 insert into kecheng (id, name, course, score)35 values (3, '王五', '历史', 45);36 insert into kecheng (id, name, course, score)37 values (3, '王五', '化学', 1);38 commit;⼆、固定⾏列转换2.1、Decode⽅式SELECT ID,NAME,SUM(DECODE(course,'语⽂',score,0)) 语⽂,--这⾥使⽤max,min都可以SUM(DECODE(course,'数学',score,0)) 数学,SUM(DECODE(course,'英语',score,0)) 英语,SUM(DECODE(course,'历史',score,0)) 历史,SUM(DECODE(course,'化学',score,0)) 化学FROM kechengGROUP BY ID ,NAME2.2、Case⽅式SELECT ID,NAME,MAX(CASE WHEN course='语⽂' THEN score ELSE 0 END) 语⽂,MAX(CASE WHEN course='数学' THEN score ELSE 0 END) 数学,MAX(CASE WHEN course='英语' THEN score ELSE 0 END) 英语,MAX(CASE WHEN course='历史' THEN score ELSE 0 END) 历史,MAX(CASE WHEN course='化学' THEN score ELSE 0 END) 化学FROM kechengGROUP BY ID ,NAME结果与上⽅⼀样2.3、wmsys.wm_concat⾏列转换函数SELECT ID,NAME,wmsys.wm_concat(course || ':'||score) courseFROM kechengGROUP BY ID ,NAME;2.4、使⽤over(partition by t.u_id)⽤法SELECT NAME,wmsys.wm_concat(course ||score) OVER (PARTITION BY NAME)FROM kecheng三、动态转换3.1、使⽤PL/SQLDECLARE--存放最终的SQLLV_SQL VARCHAR2(3000);--存放连接的SQLSQL_COMMOND VARCHAR2(3000);--定义游标CURSOR CUR ISSELECT COURSE FROM KECHENG GROUP BY COURSE;BEGIN--定义查询开头SQL_COMMOND := 'SELECT NAME ';FOR I IN CUR LOOP--将结果相连接SQL_COMMOND := SQL_COMMOND || ' ,SUM(DECODE(course,''' || I.COURSE || ''',score,0)) ' || I.COURSE;DBMS_OUTPUT.PUT_LINE(SQL_COMMOND);END LOOP;SQL_COMMOND := SQL_COMMOND || ' from KECHENG group by name';LV_SQL := 'INSERT INTO temp_ss ' || SQL_COMMOND;DBMS_OUTPUT.PUT_LINE(LV_SQL);EXECUTE IMMEDIATE LV_SQL;END;temp_ss 表。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
oracle----------行转列(动态行转不定列)----测试通过(9i)
/*物料需要数量需要仓库现存量仓库现存量仓库数量批次
A1 2 C1 C1 20 123
A1 2 C1 C2 30 111
A1 2 C1 C2 20 222
A1 2 C1 C3 10 211
A2 3 C4 C1 40 321
A2 3 C4 C4 50 222
A2 3 C4 C4 60 333
A2 3 C4 C5 70 223
我需要把上面的查询结果转换为下面的。
物料需要数量需要仓库C1 C2 C3 C4 C5
A1 2 C1 20 50 10 0 0
A2 3 C4 40 0 0 110 70
*/
---------------------------------------------------------------建表
----------------判断表是否存在
declare num number;
begin
select count(1) into num from user_tables where table_name='TEST';
if num>0 then
execute immediate 'drop table TEST';
end if;
end;
----------------建表
CREATE TABLE TEST(
WL VARCHAR2(10),
XYSL INTEGER,
XYCK VARCHAR2(10),
XCLCK VARCHAR2(10),
XCLCKSL INTEGER,
PC INTEGER
);
----------------第一部分测试数据
INSERT INTO TEST VALUES('A1', 2, 'C1', 'C1' , 20, 123);
INSERT INTO TEST VALUES('A1', 2, 'C1', 'C2' , 30, 111);
INSERT INTO TEST VALUES('A1', 2, 'C1', 'C2' , 20, 222);
INSERT INTO TEST VALUES('A1', 2, 'C1', 'C3' , 10, 211);
INSERT INTO TEST VALUES('A2', 3, 'C4', 'C1' , 40, 321);
INSERT INTO TEST VALUES('A2', 3, 'C4', 'C4' , 50, 222);
INSERT INTO TEST VALUES('A2', 3, 'C4', 'C4' , 60, 333);
INSERT INTO TEST VALUES('A2', 3, 'C4', 'C5' , 70, 223); COMMIT;
--select * from test;
---------------------------------------------------------------行转列的存储过程CREATE OR REPLACE PROCEDURE P_TEST IS
V_SQL VARCHAR2(2000);
CURSOR CURSOR_1 IS SELECT DISTINCT T.XCLCK FROM TEST T ORDER BY XCLCK;
BEGIN
V_SQL := 'SELECT WL,XYSL,XYCK';
FOR V_XCLCK IN CURSOR_1
LOOP
V_SQL := V_SQL || ',' || 'SUM(DECODE(XCLCK,''' || V_XCLCK.XCLCK || ''',XCLCKSL,0)) AS ' || V_XCLCK.XCLCK;
END LOOP;
V_SQL := V_SQL || ' FROM TEST GROUP BY WL,XYSL,XYCK ORDER BY WL,XYSL,XYCK';
--DBMS_OUTPUT.PUT_LINE(V_SQL);
V_SQL := 'CREATE OR REPLACE VIEW RESULT AS '|| V_SQL;
--DBMS_OUTPUT.PUT_LINE(V_SQL);
EXECUTE IMMEDIATE V_SQL;
END;
----------------------------------------------------------------结果
----------------执行存储过程,生成视图
BEGIN
P_TEST;
END;
----------------结果
SELECT * FROM RESULT T;
WL XYSL
XYCK C1 C2 C3 C4 C5
---------- --------------------------------------- ---------- ---------- ---------- ---------- ---------- ----------
A1 2
C1 20 50 10 0 0
A2 3
C4 40 0 0 110 70
----------------第二部分测试数据
INSERT INTO TEST VALUES('A1', 2, 'C1', 'C6' , 20, 124); INSERT INTO TEST VALUES('A2', 2, 'C1', 'C7' , 30, 121); INSERT INTO TEST VALUES('A3', 2, 'C1', 'C8' , 20, 322); COMMIT;
----------------报告存储过程,生成视图
BEGIN
P_TEST;
END;
----------------结果
SELECT * FROM RESULT T;
WL XYSL
XYCK C1 C2 C3 C4 C5 C6 C7 C8 ----- ----- -------- ------- -------- ---------- ---------- ---------- ---------- ---------- ----------
A1 2
C1 20 50 10 0 0 20 0 0
A2 2
C1 0 0 0 0 0 0 30 0
A2 3
C4 40 0 0 110 70 0 0 0
A3 2
C1 0 0 0 0 0 0 0 20
--------------- 删除实体
DROP VIEW RESULT;
DROP PROCEDURE P_TEST;
DROP TABLE TEST;。