数据库数据如图
1、多列的数据组合到一列
select concat(id,name) str from aaa
select id||name str from aaa
结果:
2、多行的数据组合到一行
select wm_concat(name) name from aaa;
结果:
3、列转行(oracle 11G)
select name, sum(nums) nums from demo group by name
select * from (select name, nums from demo) pivot (sum(nums) for name in (' 苹果 ' 苹果 , ' 橘子 ', ' 葡萄 ', ' 芒果 '));
4、行转列(Oracle 11g)
select id , name, jidu, xiaoshou from Fruit unpivot (xiaoshou for jidu in (q1, q2, q3, q4) )
注意: unpivot没有聚合函数,xiaoshou、jidu字段也是临时的变量
5、逗号分割的字符串转多行
即把
转换为:
SQL语句整理之后为:
with temp0 as (select LEVEL lv from dual CONNECT BY LEVEL <= 20) select id,substr(t.vals,instr(t.vals, ',', 1, tv.lv) + 1, instr(t.vals, ',', 1, tv.lv + 1) -(instr(t.vals, ',', 1, tv.lv) + 1)) AS name from (select id,',' || name || ',' AS vals,
(length(name || ',') - nvl(length(REPLACE(name, ',')), 0)) AS cnt
from aaa) t join temp0 tv
on tv.lv <= t.cnt order by id
重点解释:
with temp0 as (select LEVEL lv from dual CONNECT BY LEVEL <= 20)
当在sql查询时需要对有规律的一批数据进行分析处理而又不想将这批数据存入实体表时,我们可以使用with关键字临时构建一个虚拟的数据集,以便对其进行与实体表相似的sql操作,此处我们是创建了虚拟表temp0
sql语句简化为:select id,(..1..) as name from (..2..) t join temp0 tv on tv.lv <= t.cnt order by id
此处用到join函数:.left join(左联接),right join(右联接),inner join(相等联接或内联接),默认为inner join(单独join时),不作详解,可以参考http://blog.csdn.net/traceofsun/article/details/6074856
(..1..)中的语句:substr(t.vals,instr(t.vals, ',', 1, tv.lv) + 1, instr(t.vals, ',', 1, tv.lv + 1) -(instr(t.vals, ',', 1, tv.lv) + 1))
函数substr:substr(字符串,截取开始位置,截取长度) //返回截取的字符串
函数instr:INSTR(源字符串, 要查找的字符串, 从第几个字符开始, 要找到第几个匹配的序号),如select INSTR('CORPORATEFLOOR','OR', 3, 2) from dual 结果为13,即查到了最后的‘OR’了
(..2..) 中的语句:select id,',' || name || ',' AS vals,
(length(name || ',') - nvl(length(REPLACE(name, ',')), 0)) AS cnt
from aaa
',' || name || ',' :把查到的name字段前后都加上逗号
函数length:length(字符串),取字符串长度
函数REPLACE:REPLACE(源字符串,期望被替换的字符串[,期望被替换后的字符串])
函数nvl:nvl(结果表达式,默认值),如果结果表达式为空则结果=默认值,否则=结果表达式计算的结果