首页 > 数据库 > Oracle > 【原创】再谈谈行转列
今天碰到了个需求需要将数据表中数据行转列显示,也就是要将多行的数据放到同一列中。自己前几年也写过类似的文章,感觉行转列这种类似的问题及需求一直存在呀,连oracle在11g中都专门新加了个函数,专门用来处理这类需求。
言归正传,先看看上面提到的oracle11g中的这个函数:listagg,在11g系统下实验了下,确实比较给力。
代码内容:
with c as(
select 1 id,'a' name from dual union
select 2,'b' from dual union
select 2,'c' from dual)
select id,listagg(name,',')within group(order by name) names from c group by id
除了可以处理正常的行转列需求外,还可以按照特定顺序排列显示,确实比较BT,果然新版本还是有好处的。
下面说说10g的,刚刚动了下脑子写出来的,用到生成树相关的函数,代码内容:
with c as(
select 1 id,'a' name from dual union
select 2,'b' from dual union
select 2,'c' from dual)
select id,substr(sys_connect_by_path(t.name,','),2) names from
(select c.*,row_number()over(partition by id order by name) rm from c) t
where connect_by_isleaf=1
start with t.rm = 1 connect by prior t.rm+1 = t.rm and prior t.id = t.id
细节一是用到row_number函数用来生成伪列,其中也可以利用到row_number函数实现listagg中相同的order by功能,二是在生成树的规则时用到prior t.rm+1 = t.rm and prior t.id = t.id这两个条件,三是利用connect_by_isleaf函数只显示叶子那一条记录。
9i的话与10g差别不大,主要是9i中不提供connect_by_isleaf函数,这点比较悲催,换个方式解决下:
with c as(
select 1 id,'a' name from dual union
select 2,'b' from dual union
select 2,'c' from dual)
select id,max(substr(sys_connect_by_path(t.name,','),2)) names from
(select c.*,row_number()over(partition by id order by name) rm from c) t
start with t.rm = 1 connect by prior t.rm+1 = t.rm and prior t.id = t.id
group by id
区别在哪里,自己看
因为目前的环境是采用9i的库,所以只好用最后一种方法,还是新版本比较有乐趣啊
[@more@]来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/789181/viewspace-1048012/ ,如需转载,请注明出处,否则将追究法律责任。