给你看看这个:
[Q]如何实现行列转换
[A]1、固定列数的行列转换
如
student subject grade
---------------------------
student1 语文 80
student1 数学 70
student1 英语 60
student2 语文 90
student2 数学 80
student2 英语 100
……
转换为
语文 数学 英语
student1 80 70 60
student2 90 80 100
……
语句如下:
select student,sum(decode(subject,'语文', grade,null)) "语文",
sum(decode(subject,'数学', grade,null)) "数学",
sum(decode(subject,'英语', grade,null)) "英语"
from table
group by student
[Q]如何实现行列转换
[A]1、固定列数的行列转换
如
student subject grade
---------------------------
student1 语文 80
student1 数学 70
student1 英语 60
student2 语文 90
student2 数学 80
student2 英语 100
……
转换为
语文 数学 英语
student1 80 70 60
student2 90 80 100
……
语句如下:
select student,sum(decode(subject,'语文', grade,null)) "语文",
sum(decode(subject,'数学', grade,null)) "数学",
sum(decode(subject,'英语', grade,null)) "英语"
from table
group by student
select
sum(decode(substr(month)),'01',num1,0))"1月",
sum(decode(substr(month)),'02',num1,0))"2月",
sum(decode(substr(month)),'03',num1,0))"3月",
sum(decode(substr(month)),'04',num1,0))"4月",
sum(decode(substr(month)),'05',num1,0))"5月",
sum(decode(substr(month)),'06',num1,0))"6月",
sum(decode(substr(month)),'07',num1,0))"7月",
sum(decode(substr(month)),'08',num1,0))"8月",
sum(decode(substr(month)),'09',num1,0))"9月",
sum(decode(substr(month)),'10',num1,0))"10月",
sum(decode(substr(month)),'11',num1,0))"11月",
sum(decode(substr(month)),'12',num1,0)) "12月"
from biao
group by substr(month,1,4to_char(month,'yyyy-mm-dd')
字段有50个??
如果用数组,类型也很难定义。
你有没有试过二维数组,把表里数据取出来放在数组里,然后再把数组的两个下标交换就是新表的结构了。
看看那种做法效率高
--单维数组
TYPE vtmp IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER; --记录集
TYPE tmp IS RECORD
( num1 number,num2 number,num3 number,
num4 number,num5 number,num6 number,
num7 number,num8 number,num9 number,
num10 number,num11 number,num12 number);查出原表的记录,放入记录集中,然后再赋给 单维数组
---------------------- 单维数组 ------------------------DECLARE
TYPE emp_ssn_array IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;best_employees emp_ssn_array;
worst_employees emp_ssn_array;BEGIN
best_employees(1) := '123456';
best_employees(2) := '888888';worst_employees(1) := '222222';
worst_employees(2) := '666666';FOR i IN 1..best_employees.count LOOP
DBMS_OUTPUT.PUT_LINE('i='|| i || ', best_employees= ' ||best_employees(i)
|| ', worst_employees= ' ||worst_employees(i));
END LOOP;END;---------------------- 多维数组 ------------------------
DECLARETYPE emp_type IS RECORD
( emp_id employee_table.emp_id%TYPE,
emp_name employee_table.emp_name%TYPE,
emp_gender employee_table.emp_gender%TYPE );TYPE emp_type_array IS TABLE OF
emp_type INDEX BY BINARY_INTEGER;emp_rec_array emp_type_array;
emp_rec emp_type;BEGIN
emp_rec.emp_id := 300000000;
emp_rec.emp_name := 'Barbara';
emp_rec.emp_gender := 'Female';emp_rec_array(1) := emp_rec;emp_rec.emp_id := 300000008;
emp_rec.emp_name := 'Rick';
emp_rec.emp_gender := 'Male';emp_rec_array(2) := emp_rec;FOR i IN 1..emp_rec_array.count LOOP
DBMS_OUTPUT.PUT_LINE('i='||i
||', emp_id ='||emp_rec_array(i).emp_id
||', emp_name ='||emp_rec_array(i).emp_name
||', emp_gender = '||emp_rec_array(i).emp_gender);
END LOOP; END;
-------------- Result --------------
i=1, emp_id =300000000, emp_name =Barbara, emp_gender = Female
i=2, emp_id =300000008, emp_name =Rick, emp_gender = Male
1、做循环,每次从表中取出一列记录(50个字段就是五十次),再做循环(12个月就是12次)将数据拼成 insert into tablename values(值1,值2,...,值12)的样子,然后执行。出错一块回滚。
这样做会50次连接原表,但无需定义数组。
2、定义数组,一次从原表取出记录,存在数组里(这里也要做循环加,12个月就是12次)。然后做两层循环将插入语句拼好,执行(和第一种拼串方式一样)。出错一块回滚。
这样做只一次连接原表,但定义数组占用空间,给数组赋值也会占用时间。两种做法究竟哪种合适试试才知道。
INSERT INTO biao1 VALUES('aa',5,'bb','吨',varry(1).num1,varry(2).num1,varry(3).num1,varry(4).num1,varry(5).num1,varry(6).num1,varry(7).num1,varry(8).num1,varry(9).num1,varry(10).num1,varry(11).num1,varry(12).num1,varry(13).num1,varry(14).num1,varry(15).num1,varry(16).num1,varry(17).num1,varry(18).num1,varry(19).num1,varry(20).num1,varry(21).num1,varry(22).num1,varry(23).num1)用以下动态语句为什么老出错:
vkind:='aa';
vseq:=5;
vname:='bb';
vunit:='吨';FOR i IN 1..23 LOOP
vstr:=vstr||'varry('||to_char(i)||').num1,';
END LOOP;
vstr:=substr(vstr,1,length(vstr)-1)||')'; str_sql:='INSERT INTO biao1 VALUES(:1,:2,:3,:4,'||vstr;
execute immediate str_sql USING vkind,vseq,vname,vunit; 再帮忙看一下。拜托。
ORA-00904: "VARRY": 无效的标识符难道动态语句中不能用到括号?
此处应该是
vstr:=vstr|| varry(to_char(i)).num1 || ',';
FOR a IN 1..10 Loop
vtmp:='num'||to_char(a);
vstr:=vstr|| varry(to_char(i)).vtmp|| ',';
END LOOP定义成字符型,出错啊。
TYPE tmp IS RECORD
( num1 number(18,4),num2 number(18,4),num3 number(18,4);
声明PL/SQL表的语法如下:
TYPE PL/SQL表名 IS TABLE OF 数据类型 INDEX BY BINARY_INTEGER;
/*下面的例子变换一个表的行与列*/
DECLARE
TYPE phoneNum IS RECORD (
phone_no VARCHAR(13) NOT NULL DEFAULT '----',
city_code VARCHAR(4) NOT NULL DEFAULT '----',
city_name VARCHAR(8) NOT NULL DEFAULT '----',
state VARCHAR(6) NOT NULL DEFAULT '----',
type VARCHAR(6) NOT NULL DEFAULT '----'
); /*声明记录类型数据*/
TYPE emp_type_array IS TABLE OF phoneNum INDEX BY BINARY_INTEGER;/*声明多维数组*/
selPart emp_type_array; /*声明多维数组变量*/
loopCount INTEGER;
colTotal INTEGER:=5; /*总计列数*/ CURSOR curSel IS /*声明游标*/
SELECT phone_no,city_code,city_name,state,type
FROM tb_phone_no
WHERE phone_no in ('1333241','1339414','1334237','1333222','1332230');BEGIN
loopCount:=0;
OPEN curSel; /*打开游标*/
FETCH curSel INTO selPart(loopCount); /*从游标中检索数据行*/
WHILE curSel%FOUND LOOP /*当不再能找到数据时,终止查询*/
loopCount:=loopCount+1;
FETCH curSel INTO selPart(loopCount);
END LOOP;
CLOSE curSel; /*关闭游标*/ DBMS_OUTPUT.PUT_LINE('正常显示:');
FOR loopCount IN 0..selPart.count-1 LOOP
DBMS_OUTPUT.PUT_LINE(selPart(loopCount).phone_no ||
' ' || selPart(loopCount).city_code ||
' ' || selPart(loopCount).city_name ||
' ' || selPart(loopCount).state ||
' ' || selPart(loopCount).type);
END LOOP;
DBMS_OUTPUT.PUT_LINE('------------------------------------------------');
DBMS_OUTPUT.PUT_LINE('行列转换:'); FOR loopCount IN 0..colTotal-1 LOOP
DBMS_OUTPUT.PUT(selPart(loopCount).phone_no || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE('');
FOR loopCount IN 0..colTotal-1 LOOP
DBMS_OUTPUT.PUT(selPart(loopCount).city_code || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE('');
FOR loopCount IN 0..colTotal-1 LOOP
DBMS_OUTPUT.PUT(selPart(loopCount).city_name || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE('');
FOR loopCount IN 0..colTotal-1 LOOP
DBMS_OUTPUT.PUT(selPart(loopCount).state || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE('');
FOR loopCount IN 0..colTotal-1 LOOP
DBMS_OUTPUT.PUT(selPart(loopCount).type || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE('');
END;
/*运行示例*/
SQL> @d:\temp\oracle.sql
61 /
正常显示:
1332230 0417 营口 辽宁 CDMA
1333222 0411 大连 辽宁 CDMA
1334237 0427 盘锦 辽宁 CDMA
1339414 0414 本溪 辽宁 CDMA
1333241 024 沈阳 辽宁 CDMA
------------------------------------------------
行列转换:
1332230 1333222 1334237 1339414 1333241
0417 0411 0427 0414 024
营口 大连 盘锦 本溪 沈阳
辽宁 辽宁 辽宁 辽宁 辽宁
CDMA CDMA CDMA CDMA CDMA PL/SQL 过程已成功完成。
--记录集(存储单条查询结果)
TYPE tmp111 IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
TYPE tmp2 IS RECORD ( zhi tmp111 );
vtab tmp2;
--单维数组
TYPE arr2 IS TABLE OF tmp2 INDEX BY BINARY_INTEGER;
vary arr2;那么第二层就可以用循环了:
如: vary(i).zhi(i)