问题举例子如下:实际情况,就是表B的字段CODE经常要根据实际情况增减所以没法直接放在A表里面,
但是对于表A里面的每一条,B表里面关联的记录 数量、CODE 都是固定的。表A 横表结构:CUST_ID NAME TEL_NUM STATE
1 user1 12345 1
2 user2 54321 1表B纵表结构,CUST_ID 关联表AID CUST_ID CODE VALUE
1 1 ADDR 地址1
2 1 VP_FLAG 1
3 1 **** A
4 2 ADDR 地址2
5 2 VP_FLAG 0
6 2 **** B
现在想通过一个SQL查询出这样的一个结果:CUST_ID NAME TEL_NUM STATE ADDR VP_FLAG ****
1 user1 12345 1 地址1 1 A
2 user2 54321 1 地址2 0 B
如果B表里面 CODE 增加一个的话,查询结果会自动增加一列,显示每条记录的该CODE的值网上查了很多,对于纵表转横标都是固定列的求高人解决......
select ta.CUST_ID,ta.NAME,ta.TEL_NUM,ta.STATE,
(select VALUE from B where ta.CUST_ID = B.CUST_ID and B.CODE='ADDR') ADDR,
(select VALUE from B where ta.CUST_ID = B.CUST_ID and B.CODE='VP_FLAG') VP_FLAG,
(select VALUE from B where ta.CUST_ID = B.CUST_ID and B.CODE='****') STARS
from A ta;
附上建表和插入记录的SQL语句,没有加主外键限制。create table a
(
CUST_ID number(20),
NAME varchar2(20),
tel_num number(20),
state number(1)
);create table b
(
ID number(20),
CUST_ID number(20),
CODE varchar2(20),
VALUE varchar2(20)
);insert into a values(1,'user1',12345,1);
insert into a values(2,'user2',54321,1);insert into b values(1,1,'ADDR','地址1');
insert into b values(2,1,'VP_FLAG','1');
insert into b values(3,1,'****','A');
insert into b values(4,2,'ADDR','地址2');
insert into b values(5,2,'VP_FLAG','0');
insert into b values(6,2,'****','B');
比如我的例子上是 3个 ADDR、VP_FLAG、***
如果再增加一个编码,那SQL就得重写。之所以做纵表就是为了扩展性方便。
重写SQL就没意义了...
新建一个表存储结果。
给分啊~~~~DECLARE
CURSOR c_code IS
SELECT DISTINCT code FROM b;
s_sql VARCHAR2(32767);
s_sub_sql VARCHAR2(100):= ',(select value from b where ta.CUST_ID = B.CUST_ID and B.CODE=';
su_sql_create varCHAR2(32767);
BEGIN
s_sql := 'select ta.CUST_ID,ta.NAME,ta.TEL_NUM,ta.STATE';
FOR cc IN c_code loop
s_sql := s_sql || s_sub_sql ||chr(39)||cc.code||chr(39)||') '||cc.code;
END loop;
s_sql := s_sql ||' from A ta';
-- dbms_output.put_line(s_sql);
su_sql_create := 'create table coddde as '||s_sql;
EXECUTE IMMEDIATE su_sql_create;
exception
when others then dbms_output.put_line(sqlcode);
END;
/
--类似的问题以前的帖子很多哈,动态SQL行列转换酒行了,用存储过程来做:C:\Documents and Settings\Administrator>sqlplus /nologSQL*Plus: Release 10.2.0.1.0 - Production on 星期四 7月 26 15:07:47 2012Copyright (c) 1982, 2005, Oracle. All rights reserved.SQL> conn aps2/aps2
已连接。
SQL> select * from tab_a; CUST_ID NAME TEL_NUM STATE
---------- ----- ---------- ----------
1 user1 12345 1
2 user2 54321 1SQL> select * from tab_b; ID CUST_ID CODE VALUE
---------- ---------- ------- -----
1 1 ADDR 地址1
2 1 VP_FLAG 1
3 1 **** A
4 2 ADDR 地址2
5 2 VP_FLAG 0
6 2 **** B已选择6行。SQL> --创建存储过程
SQL> create or replace procedure row_to_col_func(cur out sys_refcursor)
2 as
3 sqlstr varchar2(2000):='select a.cust_id,max(a.name) as name,max(a.tel_num) as tel_num,max(a.state) as state ';
4 begin
5 for rs in (select distinct code from tab_b ) loop
6 sqlstr:=sqlstr||chr(10)||','||'max(decode(b.code,'''||rs.code||''',b.value,'''')) as "'||rs.code||'"';
7 end loop ;
8 sqlstr:=sqlstr||chr(10)||'from tab_a a,tab_b b WHERE a.cust_id=b.cust_id group by a.cust_id ' ;
9 open cur for sqlstr;
10 end row_to_col_func;
11 /过程已创建。SQL> --测试
SQL> var cur refcursor
SQL> exec row_to_col_func(:cur);PL/SQL 过程已成功完成。SQL> print cur CUST_ID NAME TEL_NUM STATE VP_FL ADDR ****
---------- ----- ---------- ---------- ----- ----- -----
1 user1 12345 1 1 地址1 A
2 user2 54321 1 0 地址2 BSQL> insert into tab_b values(7,1,'xxx','xxx');已创建 1 行。SQL> commit;提交完成。SQL> exec row_to_col_func(:cur);PL/SQL 过程已成功完成。SQL> print cur CUST_ID NAME TEL_NUM STATE VP_FL ADDR **** xxx
---------- ----- ---------- ---------- ----- ----- ----- -----
1 user1 12345 1 1 地址1 A xxx
2 user2 54321 1 0 地址2 BSQL> insert into tab_b values(8,2,'xxx','yyy');已创建 1 行。SQL> commit;提交完成。SQL> exec row_to_col_func(:cur);PL/SQL 过程已成功完成。SQL> print cur CUST_ID NAME TEL_NUM STATE VP_FL ADDR **** xxx
---------- ----- ---------- ---------- ----- ----- ----- -----
1 user1 12345 1 1 地址1 A xxx
2 user2 54321 1 0 地址2 B yyySQL>