您的位置:首页 > 数据库 > Oracle

oracle VS postgresql系列-行列转换

2016-07-13 14:07 204 查看
【需求】例如先有数据为

id  |  name
------+---------
1001 | lottu
1001 | xuan
1001 | rax
1002 | ak
1002 | vincent
现在需要转换为
id  |     names
------+----------------
1001 | lottu|xuan|rax
1002 | ak|vincent
反之;oracle,postgresql有如何对待


【列转行】
oracle
对oracle;看到这样的需求;立刻想到vm_concat,listagg函数;这样sql就出来了

select id, vm_concat(name,'|')as names from lottu01 group by id;

select id, listagg(name,'|') within group(order by null) as names from lottu01 group by id;


postgresql
同理也有对应的函数string_agg

mydb=> select id,string_agg(name,'|') from lottu01 group by id;
id  |   string_agg
------+----------------
1002 | ak|vincent
1001 | lottu|xuan|rax


【行转列】
oracle
这个一看就要使用分割函数;对oracle目前是不存在split函数
分割函数这个可以查考--http://www.cnblogs.com/lottu/p/4013751.html
当然我们可以用其他函数来替代 正则函数 regexp_substr

select id,regexp_substr(names,'[^|]+',1,level) as name from lottu02
connect by id = prior id
and prior dbms_random.value is not null
and level <= length(regexp_replace(names, '[^|]'))+1;
#或者
select id,regexp_substr(names,'[^|]+',1,level) as name from lottu02
connect by id = prior id
and prior dbms_random.value is not null
and level <= regexp_count(names, '\|')+1;


postgresql
postgresql里面有分割函数--split_part;还是不能按照上面的写法来改;因为目前的postgresql不支持 connect by语法;
不过没关系;这并不妨碍写法不能实现。
另外 postgresql针对这个有个正则函数--regexp_split_to_table;可以直接实现。

--借用with recursive的语法来替换 connect by的写法。
mydb=> with recursive t(id,lv) as(
mydb(> select id,1 lv from lottu02
mydb(> union all
mydb(> select ts.id, t.lv+1 from t, lottu02 ts where t.id = ts.id and t.lv < length(ts.names)-length(replace(ts.names,'|','')) + 1
mydb(> )
mydb-> select t1.id,split_part(t1.names,'|',t2.lv) from lottu02 t1,t t2
mydb-> where t1.id = t2.id;
id  | split_part
------+------------
1001 | lottu
1001 | xuan
1001 | rax
1002 | ak
1002 | vincent

-- 借用regexp_split_to_table轻松实现。
mydb=> select id,regexp_split_to_table(names,'\|') from lottu02;
id  | regexp_split_to_table
------+-----------------------
1001 | lottu
1001 | xuan
1001 | rax
1002 | ak
1002 | vincen
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: