近几天一直在弄Oracle-SQL的问题,涉及到了一些平时没有用到的东西,也因此而在这里郁闷了好久。现在问题得到了解决虽说不算完美。但是还是和大家一起分享一下。
行列转换之一:sum(case when.. then.. else.. end) as 语句
这种也可能是我们遇到的第一个行列转换的方法。巧妙的利用汇总和判断语句就可以解决的。
先看一个简单的基础表:如下图
create table STUDENT
(  www.2cto.com  
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递归 语句  www.2cto.com  
素材还是上面的表,下面我想得到的结果是:


 
把一个对象的各个学科的属性连接起来放入到一个列中,用字符串存放。
当时看到这个业务需求的时候,当然学生这个只是举个例子。很没有头绪。但是业务那边也急着要数据,没办法。只好硬着头皮想办法。首先就想起了这个要用连接字符串的函数,还需要判断循环之类的。于是乎就想起了这样做,创建一个自定义函数。来处理字符串不断的相加。
方法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
要说明的是:  www.2cto.com  


 
所以在使用这个函数之前,我们必须先对源数据进行处理。第一步简单的处理一下。
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  www.2cto.com  
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函数自定义。
比较复杂一点的行列转换用以上两个方法都可以实现。但是这两个方法却都存在着一些优点和缺点。但是本人建议还是使用下面的方法比较靠谱
###################################################################################################################################
###################################################################################################################################
固定列数的行列转换

student   subject   grade   
---------------------------   
student1   语文   80   
student1   数学   70   
student1   英语   60   
student2   语文   90   
student2   数学   80   
student2   英语   100   
……   
转换为     
语文   数学   英语   
student1   80   70   60   
student2   90   80   100

……   
语句如下:

[sql] view plaincopy
  1. select   student,sum(decode(subject,'语文',   grade,null))   "语文",
  2. sum(decode(subject,'数学',   grade,null))   "数学",
  3. sum(decode(subject,'英语',   grade,null))   "英语"
  4. from   table
  5. group   by   student

不固定列数行列互换

如   
c1   c2   
--------------   
1   我   
1   是   
1   谁   
2   知   
2   道   
3   不   
……

转换为   
1   我是谁   
2   知道   
3   不   
这一类型的转换必须借助于PL/SQL来完成,这里给一个例子

[sql] view plaincopy
  1. CREATE   OR   REPLACE   FUNCTION   get_c2(tmp_c1   NUMBER)
  2. RETURN   VARCHAR2
  3. IS
  4. Col_c2   VARCHAR2(4000);
  5. BEGIN
  6. FOR   cur   IN   (SELECT   c2   FROM   t   WHERE   c1=tmp_c1)   LOOP
  7. Col_c2   :=   Col_c2||cur.c2;
  8. END   LOOP;
  9. Col_c2   :=   rtrim(Col_c2,1);
  10. RETURN   Col_c2;
  11. END;
[sql] view plaincopy
  1. SQL>   select   distinct   c1   ,get_c2(c1)   cc2   from   table;

看到这里,已经有了解决思路了,在oracle中建一个function,代码如下:

[sql] view plaincopy
  1. CREATE OR REPLACE FUNCTION get_ver(tmp_boinstid VARCHAR2)
  2. RETURN   VARCHAR2
  3. IS
  4. vers   VARCHAR2(100);
  5. BEGIN
  6. FOR   cur   IN   (SELECT pln_ver FROM PMS_BUDGET_PLAN WHERE boinst_id=tmp_boinstid order by is_all_run)   LOOP
  7. vers   :=   vers||cur.pln_ver||',';
  8. END   LOOP;
  9. vers   :=   rtrim(vers,1);
  10. RETURN   vers;
  11. END get_ver;

然后使用这个函数来查询就可以了,

[sql] view plaincopy
  1. SELECT distinct p.pln_name,p.pln_year,get_ver(boinst_id) FROM PMS_BUDGET_PLAN p WHERE p.pln_type =20 and p.del_flag = -1  and boinst_id is not null

需要注意的是,由于函数中也使用了sql,所以这个方法不太适合大数据量的查询,使用时应注意。

##################################################################################################################

##################################################################################################################

oracle 动态交叉查询 行列互换 oracle动态交叉表

使用视图 动态创建视图

SQL code
CREATE OR REPLACE procedure DWDEV.dw_dis_proc(tabname in varchar2,--需要进行行转列操作的表名group_col in varchar2,--查询结果要按某列或某些列分组的字段名

column_col in varchar2,--要从行转成列的字段value_col in varchar2,--需要聚合的值字段Aggregate_func in varchar2 default 'max',--选用的聚合函数,可选,默认为maxcondition in varchar2 default '1=1',--条件语句,可选colorder in varchar2 default null,--行转列后列的排序,可选roworder in varchar2 default null,--行转列后记录的排序,可选when_value_null in varchar2 default null,--若value_col字段的值聚合后为空,则转换成该值,可选viewname in varchar2 default 'v_tmp'--创建的视图名称,可选,默认为v_tmp) Authid Current_Userasc1 sys_refcursor;v1 varchar2(1000);sqlstr varchar2(10000);countTemp number(10); beginEXECUTE IMMEDIATE 'select count(distinct '||column_col||') from '||tabname into countTemp; sqlstr :='create or replace view '||viewname||' as select '||group_col||','||Aggregate_func||'('||value_col||') as "summation",round('|| Aggregate_func||'('||value_col||')/'||countTemp||',2) as "average"';open c1 for 'select distinct '||column_col||' from '||tabname||' where '||condition|| case when colorder is not null then ' order by '||colorder end;loopfetch c1 into v1;exit when c1%notfound;sqlstr:=sqlstr||chr(10)||','||case when when_value_null is not null then 'nvl(' end||Aggregate_func||'(decode(to_char('||column_col||'),'''||v1||''','||value_col||'))'||case when when_value_null is not null then chr(44) ||when_value_null||chr(41) end||'"'||v1||'"';end loop;close c1;sqlstr:=sqlstr||' from '||tabname||' where '||condition||' group by '||group_col||case when roworder is not null then ' order by '||roworder end;execute immediate sqlstr;end dw_dis_proc;

select * from v_tmp
 

################################################################################################################################

################################################################################################################################

Oracle行列互换 横表和纵表

tb_score表

转换成:

SQL实现代码:

[sql] view plaincopyprint?
  1. create table tb_score
  2. (
  3. stu_id int,
  4. stu_name varchar2(20),
  5. stu_object varchar2(10),
  6. stu_score number(6,2)
  7. )
  8. go
  9. select * from tb_score;
  10. go
  11. insert into tb_score values(1,'andy','Chinese',80);
  12. insert into tb_score values(1,'andy','Math',70.05);
  13. insert into tb_score values(1,'andy','English',90);
  14. insert into tb_score values(2,'DK','Chinese',80.05);
  15. insert into tb_score values(2,'DK','Math',73.05);
  16. insert into tb_score values(2,'DK','English',99);
  17. go
  18. select stu_id,stu_name,sum(decode(stu_object,'Chinese',stu_score)) 语文,
  19. sum(decode(stu_object,'Math',stu_score)) 数学,
  20. sum(decode(stu_object,'English',stu_score)) 英语 from tb_score
  21. group by stu_id,stu_name;
  22. select stu_id,stu_name,sum(case stu_object when 'Chinese' then stu_score end) 语文,
  23. sum(case stu_object when 'Math' then stu_score end) 数学,
  24. sum(case stu_object when 'English' then stu_score end) 英语 from tb_score
  25. group by stu_id,stu_name;

上面两种方式都可以,

Oracle行列互换相关推荐

  1. Oracle行列互换总结

    blog文档结构图: 最近论坛很多人提的问题都与行列转换有关系,所以我对行列转换的相关知识做了一个总结,希望对大家有所帮助,同时有何错疏,恳请大家指出,我也是在写作过程中学习,算是一起和大家学习吧! ...

  2. oracle表行列权限,Oracle行列互换 横表和纵表

    /*在实际使用sql工作中总会碰到将某一列的值放到标题中显示.就是总说的行列转换或者互换. 比如有如下数据: ID NAME KECHENG CHENGJI -- ---------- ------- ...

  3. oracle 行列对应,Oracle行列互换 横表和纵表

    /* 在实际使用sql工作中总会碰到将某一列的值放到标题中显示.就是总说的行列转换或者互换. 比如有如下数据: ID NAME KECHENG CHENGJI -- ---------- ------ ...

  4. oracle行列互换总结___reference 小麦苗

    1.概述 行列转换包括以下六种情况: 1> 列转行 2> 行转列 3> 多列转换成字符串 4> 多行转换成字符串 5> 字符串转换成多列 6> 字符串转换成多行 下 ...

  5. oracle行列互换sql,解决Oracle行列转换问题的一个方法

    不好意思,编译错误,可能是版本的问题 其实,实现的方法很简单,请参考精华帖子 下面是源文件 ,我是的数据库版本是9.2.0.1,OS为NT [PHP] ---Author: Accelerator - ...

  6. Oracle笔记 之 行列互换

    行列互换 行转列 数据集 YEAR MONTH VALS 2000 1 100 2000 2 100 2000 3 200 2000 1 100 2000 2 100 2000 3 100 2001 ...

  7. ACMNO.24 C语言-转置矩阵 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换。 输入 一个3x3的矩阵 输出 转置后的矩阵 样例

    题目描述 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换. 输入 一个3x3的矩阵 输出 转置后的矩阵 样例输入 1 2 3 4 5 6 7 8 9 样例输出 1 4 7 2 5 8 3 ...

  8. sortable 拖拽时互换目标的位置_报表如何实现行列互换效果?

    通常我们设计的二维的交叉报表,横向的维度和纵向的维度是固定的,而用户希望更希望能根据自己的需要快速转换横向纵向维度来查看报表. 如上图所示,我们通过点击一个按钮或文字,就可将报表的行列维度互相转换,这 ...

  9. excel行列互换_Excel如何实现行列数据互换?其实除了复制粘贴,还能这样操作...

    将excel的行列互换,是我们会经常遇到的操作.当然,如果数据少,凭着多年的Ctrl+C.Ctrl+V,行列互换不在话下,但如果数据量一多呢?我们该如何是好?如下图,图2看起来很长不是太美观,如果想把 ...

最新文章

  1. SCAU RP Test —— 因式分解与组合
  2. spring boot 启动 nested exception is java.lang.IllegalStateException
  3. 浅谈 PodDisruptionBudgets
  4. 在html中横坐标是纵坐标,excel 作图中次横坐标及次纵坐标的调试,以及excel自定义轴标签的步骤方法...
  5. 只安装和配置instantclient,用plsql developer,navicat for oracle,sqlplus连接oracle数据库 ....
  6. SpringMVC处理请求或响应数据
  7. UNI使用蓝牙连接设备传输数据
  8. 小红书重拳治理虚假种草 再起诉3家通告平台、MCN机构
  9. paip.undefined reference to MainWindow::xxx from moc_mainwindow.cpp错误解决
  10. 【图像加密】基于matlab DNA混沌系统图像加密【含Matlab源码 1190期】
  11. Java程序调用linux脚本-简单版
  12. im即时通讯源码(软件)支持封装APP和H5开源php版
  13. 单片机中断原理及定时器详解
  14. 无线路由器pppoe服务器,详解Volans飞鱼星路由器怎么设置PPPOE服务器
  15. 新猿木子李:0基础学python培训教程 Python操作Redis之有序集合类型
  16. 【零知识证明】数独解的例子解释零知识证明
  17. 产品包装设计在品牌和营销中的重要性
  18. SQL 数据库 学习 011 关系、一对一、一对多、多对多
  19. GitHub 上值得收藏的100个精选前端项目!
  20. 培训机构要不要去 适合谁去

热门文章

  1. win10explorer.exe任务栏卡死修复
  2. 抖音直播公会怎么入驻呢?
  3. DataOps To be or NOT to be?
  4. 中国版我的世界弹出java_我的世界中国版JAVA不删档测试问题指引
  5. 微信小程序发布审核基本步骤(带图)
  6. 【转载】man rsync翻译(rsync命令中文手册)
  7. 学习日记——腾讯云物联网平台
  8. 电竞数据帮助行业发展 体育数据助力产业发展
  9. 树莓派OpenCV警告libEGL warning: DRI2: failed to authenticate(待续)
  10. cups共享linux打印机_Linux学习之CUPS实现网络打印机