oracle列转行方法总结

多行转单行的SQL技巧
本文介绍三种将数据库中多行记录转换为单行字符串的方法,包括使用自定义函数、连接路径函数及窗口函数等高级SQL技术。

 

 

方法一:
----------------------------------------------------------------
---Muti-row to line(col2row)
----------------------------------------------------------------
create or replace type str_tab is table of varchar2(20);
/
grant all on str_tab to public;
create public synonym str_tab for str_tab;
create or replace function col2row(pv in str_tab) return varchar2
is
  ls varchar2(4000);
begin
  for i in 1..pv.count loop
    ls := ls || pv(i);
  end loop;
  return ls;
end;
/
grant execute on col2row to public;
create public synonym col2row for col2row;
----------------------------------------------------------------
--multi column,convert one column base on another column, for example
----------------------------------------------------------------
create table t(id number,name varchar2(10));
insert into t values(1,'Joan');
insert into t values(1,'Jack');
insert into t values(1,'Tom');
insert into t values(2,'Rose');
insert into t values(2,'Jenny');
---------------------------------------------------------------
SQL(c3dev)>select * from t;
        ID NAME
---------- ----------
         1 Joan
         1 Jack
         1 Tom
         2 Rose
         2 Jenny
---------------------------
--column to row
---------------------------
SQL(c3dev)>column names format a80;
SQL(c3dev)>set line 120
SQL(c3dev)>select t0.id,
  2     col2row(cast(multiset(select name from t where t.id = t0.id) as str_tab)) names
  3  from (select distinct id from t) t0;
        ID NAMES
---------- --------------------------------------------------------------------------------
         1 JoanJackTom
         2 RoseJenny

----------------------------------------------------------------
--single column,convert multil row to one row, for example
----------------------------------------------------------------
create table t1(name varchar2(20));
insert into t1 values('Chen');
insert into t1 values('Chuan');
insert into t1 values('Zhong');
SQL(c3dev)>select * from t1;
NAME
--------------------
Chen
Chuan
Zhong
---------------------------
--column to row
---------------------------
select col2row(cast(multiset(select name from t1) as str_tab)) names from t1 where rownum=1
SQL(c3dev)>select col2row(cast(multiset(select name from t1) as str_tab)) names from t1 where rownum=1;
NAMES
--------------------------------------------------------------------------------
ChenChuanZhong

--if need to add list separator
SQL(c3dev)>select col2row(cast(multiset(select name||' ' from t1) as str_tab)) names from t1 where rownum=1;
NAMES
--------------------------------------------------------------------------------
Chen  Chuan Zhong
 
方法二:
create table t2(col1 varchar2(10),col2 varchar2(10));
insert into t2 values('001','vl1');
insert into t2 values('001','vl2');
insert into t2 values('001','vl3');
insert into t2 values('002','vl1');
insert into t2 values('002','vl2');
SELECT COL1,LTRIM(MAX(SYS_CONNECT_BY_PATH(COL2,',')),',') COL2
 FROM
 (
 SELECT COL1,COL2,MIN(COL2) OVER(PARTITION BY COL1) COL2_MIN,
 (ROW_NUMBER() OVER(ORDER BY COL1,COL2))+(DENSE_RANK() OVER (ORDER BY COL1)) NUMID
 FROM T2
 )
 START WITH COL2=COL2_MIN CONNECT BY NUMID-1=PRIOR NUMID
 GROUP BY COL1;
COL1       COL2
---------- ----------------------------------------
001        vl1,vl2,vl3
002        vl1,vl2

 
 方法三(需要知道确定有几行):
 SELECT deptno, dname, emps
  FROM (SELECT d.deptno, d.dname,
               RTRIM
                  (   e.ename
                   || ', '
                   || LEAD (e.ename, 1) OVER (PARTITION BY d.deptno ORDER BY e.ename)
                   || ', '
                   || LEAD (e.ename, 2) OVER (PARTITION BY d.deptno ORDER BY e.ename)
                   || ', '
                   || LEAD (e.ename, 3) OVER (PARTITION BY d.deptno ORDER BY e.ename)
                   || ', '
                   || LEAD (e.ename, 4) OVER (PARTITION BY d.deptno ORDER BY e.ename)
                   || ', '
                   || LEAD (e.ename, 5) OVER (PARTITION BY d.deptno ORDER BY e.ename),
                   ', '
                  ) emps,
               ROW_NUMBER () OVER (PARTITION BY d.deptno ORDER BY e.ename) x
          FROM emp e, dept d
         WHERE d.deptno = e.deptno)
 WHERE x = 1
/
    DEPTNO DNAME          EMPS
---------- -------------- ----------------------------------------------------------------------
        10 ACCOUNTING     CLARK, KING, MILLER
        20 RESEARCH       ADAMS, FORD, JONES, SCOTT, SMITH
        30 SALES          ALLEN, BLAKE, JAMES, MARTIN, TURNER, WARD

 

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值