请问各位高人,有一张表 source 其内容如下:
----------------------------------------------------NAME----PHONE----ADRESS <列头>aaa-----123456---adress1111 <表内容>
aaa-----123456---adress1111
aaa-----123456---adress2222
ddddddd-----66645655---adress3333
eeeeeeee-----996456666---adress4444--------------------------------------------------
现在我要转成 Target 其内容应如下:-----------------------------------------------------------------
NAME----PHONE----ADRESS1---adress2----adress3---adress4
aaa-----123456--- 2 ---1 ----0 ---0
ddddddd--66645655--0 ----0 ----1 ---0
eeeeeeee--996456666--0 ----0 ----0 ---1
---------------------------------------------------------------就是把source表的数据中的 ADRESS列的内容分离出来,分离列,进行统计.目的就是把 NAME 和 PHONE 中内容相同的统计为一行(即一条记录),
再对ADRESS列的相应内容分出很多列(具体有多少列取决与 distinct(ADRESS) ).
请问该怎么实现???
----------------------------------------------------NAME----PHONE----ADRESS <列头>aaa-----123456---adress1111 <表内容>
aaa-----123456---adress1111
aaa-----123456---adress2222
ddddddd-----66645655---adress3333
eeeeeeee-----996456666---adress4444--------------------------------------------------
现在我要转成 Target 其内容应如下:-----------------------------------------------------------------
NAME----PHONE----ADRESS1---adress2----adress3---adress4
aaa-----123456--- 2 ---1 ----0 ---0
ddddddd--66645655--0 ----0 ----1 ---0
eeeeeeee--996456666--0 ----0 ----0 ---1
---------------------------------------------------------------就是把source表的数据中的 ADRESS列的内容分离出来,分离列,进行统计.目的就是把 NAME 和 PHONE 中内容相同的统计为一行(即一条记录),
再对ADRESS列的相应内容分出很多列(具体有多少列取决与 distinct(ADRESS) ).
请问该怎么实现???
解决方案 »
- exp/imp导入导出问题
- 如何配置Standby Database Standby Site 的 ini.ora文件
- Oracle中的时间类型格式问题
- 一个多表查询的问题
- 将多个表a1,a2...(结构一样)的某些字段的数据导到一个表b(b的结构包含a需要导的字段,另外多出字段a没有的)里面
- 请教:使用SQL Server的DTS时出现的问题
- 在ORACLE 中用什么字段类型存储大量字符信息
- 使用keep pool后,数据无法缓存,该如何解决?
- 字段更新追加问题
- Oracle where语句中等号两边的是否可以互换?
- dblink insert数据到remote,varchar2型的字段,丢失.
- 如何用一条sql语句实现数据分列
它里面的数据可能是:ADRESS
100001
100001
100003
100003
100005
aaaaaa
aaaaaa 777777
777777
777777
777777
......那么增加的列就有 <100001>,<100003>,<100005>,<aaaaaa>,<777777>那么结合问题,我现在的列就有:
NAME----PHONE----ADRESS----100001----100003----100005---aaaaaa----777777
翻了一下百度,好像decode可以用,但我的列是变的,不知道怎样弄!
固定列数的做法
select NAME,PHONE,
sum(decode(ADRESS),'adress1111',1,0) ADRESS1,
sum(decode(ADRESS),'adress2222',1,0) ADRESS2
from source
group by NAME,PHONE
我对SQL函数和存储过程不熟,不知道怎样去弄,
1,指定一个参数(表的名字)
2.我们可以通过 "distinct ADRESS" 返回所有的ADRESS列中的字段(我们需要动态加入的)
3,写一个FOR循环增加列......SELECT ta.*, a[1],a[2],a[3]...a[i] FROM......
请各位大侠指点迷津~~~~
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;
2、不定列行列转换
如
c1 c2
--- -----------
1 我
1 是
1 谁
2 知
2 道
3 不
……
转换为
1 我是谁
2 知道
3 不
这一类型的转换可以借助于PL/SQL来完成,这里给一个例子
CREATE OR REPLACE FUNCTION get_c2(tmp_c1 NUMBER)
RETURN VARCHAR2
IS
Col_c2 VARCHAR2(4000);
BEGIN
FOR cur IN (SELECT c2 FROM t WHERE c1=tmp_c1) LOOP
Col_c2 := Col_c2||cur.c2;
END LOOP;
Col_c2 := rtrim(Col_c2,1);
RETURN Col_c2;
END;
select distinct c1 ,get_c2(c1) cc2 from table;
或者不用pl/sql,利用分析函数和 CONNECT_BY 实现:
SELECT c1, SUBSTR (MAX (SYS_CONNECT_BY_PATH (c2, ';')), 2) NAME
FROM (SELECT c1, c2, rn, LEAD (rn) OVER (PARTITION BY c1 ORDER BY rn) rn1
FROM (SELECT c1, c2, ROW_NUMBER () OVER (ORDER BY c2) rn
FROM t))
START WITH rn1 IS NULL
CONNECT BY rn1 = PRIOR rn
GROUP BY c1;
3、列数不固定(交叉表行列转置)
这种是比较麻烦的一种,需要借助pl/sql:
原始数据:
CLASS1 CALLDATE CALLCOUNT
1 2005-08-08 40
1 2005-08-07 6
2 2005-08-08 77
3 2005-08-09 33
3 2005-08-08 9
3 2005-08-07 21
转置后:
CALLDATE CallCount1 CallCount2 CallCount3
------------ ---------- ---------- ----------
2005-08-09 0 0 33
2005-08-08 40 77 9
2005-08-07 6 0 21
试验如下:
1). 建立测试表和数据
CREATE TABLE t(
class1 VARCHAR2(2 BYTE),
calldate DATE,
callcount INTEGER
);
INSERT INTO t(class1, calldate, callcount)
VALUES ('1', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 40);
INSERT INTO t(class1, calldate, callcount)
VALUES ('1', TO_DATE ('08/07/2005', 'MM/DD/YYYY'), 6);
INSERT INTO t(class1, calldate, callcount)
VALUES ('2', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 77);
INSERT INTO t(class1, calldate, callcount)
VALUES ('3', TO_DATE ('08/09/2005', 'MM/DD/YYYY'), 33);
INSERT INTO t(class1, calldate, callcount)
VALUES ('3', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 9);
INSERT INTO t(class1, calldate, callcount)
VALUES ('3', TO_DATE ('08/07/2005', 'MM/DD/YYYY'), 21);
COMMIT ;
2). 建立ref cursor准备输出结果集
CREATE OR REPLACE PACKAGE pkg_getrecord
IS
TYPE myrctype IS REF CURSOR;
END pkg_getrecord;
/
3). 建立动态sql交叉表函数,输出结果集
CREATE OR REPLACE FUNCTION fn_rs
RETURN pkg_getrecord.myrctype
IS
s VARCHAR2 (4000);
CURSOR c1 IS
SELECT ',sum(case when Class1='
|| class1
|| ' then CallCount else 0 end)'
|| ' "CallCount'
|| class1
|| '"' c2
FROM t
GROUP BY class1;
r1 c1%ROWTYPE;
list_cursor pkg_getrecord.myrctype;
BEGIN
s := 'select CallDate ';
OPEN c1;
LOOP
FETCH c1 INTO r1;
EXIT WHEN c1%NOTFOUND;
s := s || r1.c2;
END LOOP;
CLOSE c1;
s := s || ' from T group by CallDate order by CallDate desc ';
OPEN list_cursor FOR s;
RETURN list_cursor;
END fn_rs;
/
4). 测试在sql plus下执行:
var results refcursor;
exec :results := fn_rs;
print results;
CALLDATE CallCount1 CallCount2 CallCount3
--------------- ---------- ---------- ----------
2005-08-09 0 0 33
2005-08-08 40 77 9
2005-08-07 6 0 21
然后判断是否在现有表列之中,如果有,则Null;
无则进行创建,所以Procedure中还需要加上一个创建表列的子程序
然后接上面的脚本