最近几天一直在弄Oracle-SQL的问题,涉及到了一些平时没有用到的东西,也因此而在这里郁闷了好久。现在问题得到了解决虽说不算完美。但是还是和大家一起分享一下。

行列转换之一:sum(case when.. then.. else.. end) as 语句

这种也可能是我们遇到的第一个行列转换的方法。巧妙的利用汇总和判断语句就可以解决的。

先看一个简单的基础表:如下图

create table STUDENT
(
  STUNAME      NVARCHAR2(50),
  SUBJECTNAME  NVARCHAR2(50),
  SUBJECTSCORE NUMBER
)

表中有两个人的成绩,每一行代表每个学生该学科的成绩。这个也是我们初学SQL时候很常见的一个表结构了。

要求:把上面的多行值以学生为单位转化为2行值,可以很直观的看出每个学生的各科成绩。于是乎便有了下面的语句。

select  
s.stuname,
sum(case when s.subjectname='语文' then  s.subjectscore else 0 end  )  as 语文成绩,
sum(case when s.subjectname='数学' then  s.subjectscore else 0 end  )  as 数学成绩,
sum(case when s.subjectname='英语' then  s.subjectscore else 0 end  )  as 英语成绩
from student s
group by s.stuname
order by s.stuname

执行后所得结果:

上面的做法也很容易让人理解,在这里就不多说了,但是上面的也是有局限性的。因为此处毕竟存在着一些固定值。比如case  中的“语文,数学。。”不过遇到小的业务需求,还是可以拿来直接用的。比如一个学生成绩管理系统这个就可以满足了。

行列转换之二:sys_connect_by_path系统函数,自定义函数,connect by sname = prior sname and rank-1 = prior rank递归 语句

素材还是上面的表,下面我想得到的结果是:

把一个对象的各个学科的属性连接起来放入到一个列中,用字符串存放。

当时看到这个业务需求的时候,当然学生这个只是举个例子。很没有头绪。但是业务那边也急着要数据,没办法。只好硬着头皮想办法。首先就想起了这个要用连接字符串的函数,还需要判断循环之类的。于是乎就想起了这样做,创建一个自定义函数。来处理字符串不断的相加。

方法1:自定义函数,循环

CREATE OR REPLACE FUNCTION getallsubject(parameter varchar2)--有参数方法,字符串
RETURN varchar2
IS
return_str varchar2(4000);--该方法返回一个字符串。
BEGIN
FOR rs IN 
(
SELECT  s.subjectname||':'||s.subjectscore as allshow 
FROM student s
WHERE s.stuname=parameter--当参数一直符合条件 for循环插入结果集rs
) LOOP
return_str:=return_str||rs.allshow;--loop所有字符串,相加
END LOOP;
RETURN return_str;
END;

执行select s.stuname,getallsubject(s.stuname) from  student s

可见,改方法对每一行值都进行了判断,产生了多条记录。然后select distinct s.stuname,getallsubject(s.stuname) from  student s

效果:

得到了想要的结果。

方法2:利用oracle自带的sys_connect_by_path

要说明的是:

所以在使用这个函数之前,我们必须先对源数据进行处理。第一步简单的处理一下。

create table stu1 as

select s.stuname sname,s.subjectname||s.subjectscore  sshow from student s

--
select *from stu1

如下所示:

OK下面就可以写语句了。

select sname as 姓名,allstr 详细描述 from 
(
  select sname,allstr,
  row_number() over(partition by sname order by sname,curr_level desc) ename_path_rank
  from (
         select sname,sshow,rank,level as curr_level,
         ltrim(sys_connect_by_path(sshow,','),',') allstr from --把所有字符串相加
         (
           select s1.sname,s1.sshow,row_number() over(partition by s1.sname order by s1.sname,s1.sshow) rank
           from stu1 s1 order by s1.sname,s1.sshow--创建树关系,name可以作为parentid,rank可以作为childid
         ) connect by sname = prior sname and rank-1 = prior rank
       )
)
where ename_path_rank=1;

执行结果:

也得到了我们想要的结果。当然不用学科之间的间隔符我们可以用replace函数自定义。

比较复杂一点的行列转换用以上两个方法都可以实现。但是这两个方法却都存在着一些优点和缺点。但是本人建议还是使用下面的方法比较靠谱。

虽然结合上面的各种方法解决了这个问题,但是Oracle中字符类型值不能大于4000字节这个问题还一直没解决。我在想有没有一种数据类型,我可以往里面想放多少字节就可以放多少字节的呢。。欢迎各位高手指导!希望可以帮得上遇到该问题的或者是即将遇到该问题的朋友们。

Oracle行列转换的思考与总结的更多相关文章

  1. oracle 行列转换

    oracle 行列转换列名如果是数字,用双引号包住  如下: --  建表 create table workinfo(wid integer primary key,sid integer ,CON ...

  2. oracle行列转换函数的使用

    oracle 10g wmsys.wm_concat行列转换函数的使用: 首先让我们来看看这个神奇的函数wm_concat(列名),该函数可以把列值以","号分隔起来,并显示成一行 ...

  3. Oracle行列转换

    一.建表与插入数据 1.1.建表 create table kecheng ( id NUMBER, name ), course ), score NUMBER ); insert into kec ...

  4. oracle行列转换总结-转载自ITPUB

    原贴地址:http://www.itpub.net/thread-1017026-1-1.html 谢谢原贴大人 最近论坛很多人提的问题都与行列转换有关系,所以我对行列转换的相关知识做了一个总结, 希 ...

  5. Oracle 行列转换总结

    行列转换包括以下六种情况:*列转行*行转列*多列转换成字符串*多行转换成字符串*字符串转换成多列*字符串转换成多行 下面分别进行举例介绍. 首先声明一点,有些例子需要如下10g及以后才有的知识:a.掌 ...

  6. oracle 行列转换函数之WM_CONCAT和LISTAGG的使用(一)

    一.wm_concat函数 wm_concat能够实现同样的功能,但是有时在11g中使用需要用to_char()进行转换,否则会出现不兼容现象(WMSYS.WM_CONCAT: 依赖WMSYS 用户, ...

  7. [Oracle]行列转换(行合并与拆分)

    使用wmsys.wm_concat 实现行合并 在 Oracle  中, 将某一个栏位的多行数据转换成使用逗号风格的一行显示.能够使用函数  wmsys.wm_concat 达成. 这个在上一篇 or ...

  8. oracle 行列转换的运用

    问题: 员工表: A(E_ID,NAME,) 部门表:  B(D_ID,D_NAME) 员工与部门关系:C(ID,E_ID,D_ID) SELECT  A.E_ID,A.NAME ,B.D_NAME ...

  9. Oracle行列转换case when then方法案例

    select (select name from t_area where id=areaid) 区域, end) 一月, end) 二月, end) 三月, end) 四月, end) 五月, en ...

随机推荐

  1. [svc]Iaas Paas Saas区别

    https://www.zhihu.com/question/20387284

  2. ReportNG测试报告的定制修改(二)

    上一篇文章修改了一些基本的ReportNG信息,链接:https://www.cnblogs.com/mrjade/p/9912073.html,本文将继续带大家进行修改,重点是添加饼图 1.修改测试 ...

  3. stock article

    stock 征服星辰大海 http://www.tianya.cn/95789158 论坛_悟道股市_天涯社区 http://www.tianya.cn/108318593/bbs?t=post 当下 ...

  4. Debug文件夹是什么

    debug是一个隐藏的对象,用于进行和调试相关的工作.是系统调试文件夹,用来存放系统运行过程中调试模块的日志文件,以便管理员根据这些日志文件来发现计算机所存在的问题.其中“UserMode”文件夹下存 ...

  5. php结合msf反弹内网shell

    感谢: perl6大佬分享的姿势. MSF: msf > use payload/php/bind_phpmsf exploit(handler) > set PAYLOAD payloa ...

  6. javascript-删除节点

    任务目的: 每点击一下按钮删除一个标签. 掌握到了: 这里是主要学习到了parentNote以及removeChild两个DOM属性. parentNote:parent英译为父亲,Note英译为节点 ...

  7. Python内置的数据类型--list,tuple

    1. list Python内置的一种数据类型是列表:list. list是一种有序的集合,可以随时添加和删除其中的元素. 最后一个元素的索引是len(classmates) - 1,用-1做索引,直 ...

  8. MongoDB学习之(一)安装

    第一步:下载MongoDB的安装版进行安装 https://pan.baidu.com/s/1X3hIqORJ61TCG1UJ_yr6ag 由于第二次安装出现一些问题,所有还是记录一下,免得以后踩坑. ...

  9. [转]Handler学习笔记(二)

    一.一个问题 有这样一个问题值得我们思考,若把一些类似于下载的功能(既耗时且不一定有结果)写在Activity(主线程)里,会导致Activity阻塞,长时间无响应,直至页面假死(如果5秒钟还没有完成 ...

  10. linux实现防止恶意扫描 PortSentry

    linux实现防止恶意扫描 PortSentry   脚本 open 摘要: 端口做为服务器的大门安全很重要,当服务器运行很多服务时并向外提供服务,为防止有人恶意侦测服务器用途,可使用portsent ...