多字段的行转列查询?

gfyhlq 2005-09-29 09:16:34
原表记录:
月份 字段1 字段2 字段3 ... 字段50

2005-01 1 1 1 ... 1
2005-02 2 2 2 ... 2
..
2005-12 12 12 12 ... 12

查询结果:
字段 1月 2月 3月 ... 12月

字段1 1 2 3 ... 12
字段2 1 2 3 ... 12
...
字段50 1 2 3 ... 12

然后要把查询结果一条一条插入一个新表中,我想用decode()函数先把个个字段的记录查出来,一次查一个字段的记录,但这样有多少个字段就要循环多少次查询,会影响效率,是否可以一次就把要的结果查出来,或者把记录存到数组中,然后再循环插入新表。大家有没有什么好的办法。谢谢!
...全文
782 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
gfyhlq 2005-09-30
  • 打赏
  • 举报
回复
关键是第二层用循环比较难实现,如果字段太多,要一个一个写,很麻烦。
DF_4B 2005-09-30
  • 打赏
  • 举报
回复
▲多维数组(表)
声明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 过程已成功完成。
gfyhlq 2005-09-30
  • 打赏
  • 举报
回复
我这里只能上MSN,账号是:gfylj@hotmail.com
gfyhlq 2005-09-30
  • 打赏
  • 举报
回复
谢谢大家的帮助,特别是waterfirer(水清)
gfyhlq 2005-09-30
  • 打赏
  • 举报
回复
如果记录集这样定义:
--记录集(存储单条查询结果)
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)
waterfirer 2005-09-29
  • 打赏
  • 举报
回复
我觉得这么写起来很麻烦,字段多要做循环,再写动态sql。
你有没有试过二维数组,把表里数据取出来放在数组里,然后再把数组的两个下标交换就是新表的结构了。
看看那种做法效率高
gfyhlq 2005-09-29
  • 打赏
  • 举报
回复
是的,都是数值型的,如果字段很多,SQL语句怎么写,里面的num1能不能用一个变量来代替?
waterfirer 2005-09-29
  • 打赏
  • 举报
回复
你这些数据的类型应该是一样的啊,要不你怎么转?
gfyhlq 2005-09-29
  • 打赏
  • 举报
回复
这样只查询出一个字段的记录,
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个??
如果用数组,类型也很难定义。
waterfirer 2005-09-29
  • 打赏
  • 举报
回复
楼主试过用数组做吗?哪个效率高?
xmankevin1980xman 2005-09-29
  • 打赏
  • 举报
回复
给你看看这个:
[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
辉说慧语 2005-09-29
  • 打赏
  • 举报
回复
帮你顶了!
waterfirer 2005-09-29
  • 打赏
  • 举报
回复
有你的联系方式吗?
在那上面说吧,这里反馈的太慢了。
gfyhlq 2005-09-29
  • 打赏
  • 举报
回复
如果RECORD记录集中的项名称不能用动态的来写,那就不能进行第二层循环了。
TYPE tmp IS RECORD
( num1 number(18,4),num2 number(18,4),num3 number(18,4);
gfyhlq 2005-09-29
  • 打赏
  • 举报
回复
怎么定义,类型要定义成什么。
FOR a IN 1..10 Loop
vtmp:='num'||to_char(a);
vstr:=vstr|| varry(to_char(i)).vtmp|| ',';
END LOOP

定义成字符型,出错啊。
waterfirer 2005-09-29
  • 打赏
  • 举报
回复
直接把numj定义成j,然后写成varry(to_char(i)).j看看行不行
gfyhlq 2005-09-29
  • 打赏
  • 举报
回复
如果num1中1也要写成动态的,怎么写啊?

vstr:=vstr|| varry(to_char(i)).num?? || ',';
waterfirer 2005-09-29
  • 打赏
  • 举报
回复
vstr:=vstr||'varry('||to_char(i)||').num1,';
此处应该是
vstr:=vstr|| varry(to_char(i)).num1 || ',';
gfyhlq 2005-09-29
  • 打赏
  • 举报
回复
执行上面的语句,出现下面错误信息:
ORA-00904: "VARRY": 无效的标识符

难道动态语句中不能用到括号?
gfyhlq 2005-09-29
  • 打赏
  • 举报
回复
还是想用第二种方法,因为如果原表不止是一个表,而是要从多个表中取数据,就只能用第二种方法。

如果插入语句是:
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;

再帮忙看一下。拜托。
加载更多回复(6)

17,377

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 基础和管理
社区管理员
  • 基础和管理社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧