最近几天一直在弄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. Mysql修改时间的年月日,时分秒保持不变语句

    比如时间为 “2015-01-05 14:32:21” 修改为“2015-01-06 14:32:21” 修改内容为修改yyyy-mm-dd为对应的日期,时间不变. HOUR,TIME(StatusU ...

  2. jq 跳转方式汇总

    按钮式: <INPUT name="pclog" type="button" value="GO" onClick="loc ...

  3. DMA2D 图形加速器简介

    在实际使用 LTDC 控制器控制液晶屏时,使 LTDC 正常工作后,往配置好的显存地址写入要显示的像素数据, LTDC 就会把这些数据从显存搬运到液晶面板进行显示,而显示数据的容量非常大,所以我们希望 ...

  4. .Net应该学什么怎么学(一)

    更新时间:2012年06月05日18时21分 来源:传智播客.Net 上篇<学了.Net做什么开发>中我讲到了目前.Net开发主要方向是Web开发,因此在本篇中我将主要讲解做Web开发要学 ...

  5. iosxcode7以后免证书真机测试方法如下

    步骤比较简单,我就简单总结一下. 1. 进入xcode,菜单栏选择xcode –> preferences (快捷键 command + ,)在Accounts选项卡添加自己的Apple ID ...

  6. 【Unity笔记】给UGUI元素添加交互性

    如果想给UGUI元素添加交互性,如使一张图片能够被点击,具有normal.Highlighted.Pressed三态,可以给该物体添加组件Selectable. 已经具有交互性的物体不能再添加Sele ...

  7. 【C#】往按钮事件中传递自定义参数

    情景:代码动态生成的按钮,需要自定义点击事件.但是生成的点击事件的参数是固定的,如何才能传入自定义的参数? Button btn = new Button() { Content = "这是 ...

  8. 【C#/WPF】修改图像的DPI、Resolution

    问题: WPF中默认使用的图像的DPI是96.如果我们使用的图素的DPI不是96时(比如是72),那么WPF会把图片的DPI自动改为96,导致图像加载出来的实际大小Width和Height会比想要的大 ...

  9. C语言 · 最大最小值

    算法提高 题目1 最大最小值   时间限制:1.0s   内存限制:1.0GB      问题描述 给定 N 个整数,请你找出这 N 个数中最大的那个和最小的那个. 输入格式 第一行包含一个正整数 N ...

  10. ARM板卡ftp客户端应用

    BusyBox已集成命令tftp,可通过tftp上传或下载文件: Usage: tftp [OPTIONS] HOST [PORT] Transfer a file from/to tftp serv ...