时间:2021-07-01 10:21:17 帮助过:18人阅读
平时做报表统计数据时,常遇到行列互转,最后有总计等要求的报表式。 注:下面的sql都是在oracle 10g下写的。 假如现有一张这样的数据表: SELECT * FROM studentscores ; 多行转多列 现客户要求这样的式显示 这样的式来显示成绩。 方法一: WITH t1 AS( SEL
平时做报表统计数据时,常遇到行列互转,最后有总计等要求的报表格式。
注:下面的sql都是在oracle 10g下写的。
假如现有一张这样的数据表:
- SELECT * FROM studentscores ;
现客户要求这样的格式显示
这样的格式来显示成绩。
方法一:
- WITH t1 AS(
- SELECT st1.name NAME,st1.score chinese ,0 math, 0 english
- FROM studentscores st1
- WHERE st1.object = '语文'
- ),
- t2 AS(
- SELECT st2.name NAME,0 chinese ,st2.score math, 0 english
- FROM studentscores st2
- WHERE st2.object = '数学'
- ),
- t3 AS(
- SELECT st3.name NAME,0 chinese ,0 math, st3.score english
- FROM studentscores st3
- WHERE st3.object = '英语'
- )
- SELECT t.name 姓名, SUM(t.chinese) 语文, SUM(t.math) 数学, SUM(t.english) 英语
- FROM(
- SELECT t1.name,t1.chinese,t1.math,t1.english
- FROM t1
- UNION ALL
- SELECT t2.name,t2.chinese,t2.math,t2.english
- FROM t2
- UNION ALL
- SELECT t3.name,t3.chinese,t3.math,t3.english
- FROM t3
- )t。
- GROUP BY t.name
方法二
方法二对于新手来说,也许不能一下子弄明白,不妨这样来想想。如果我要求你统计每个学生的总分,你是不是很快就可以写出来了select st.name,sum(st.score) from studentscores group by name.那么在这条语句的基础上,我改一改select st.name,sum(decode(st.object,'语文',st.score,0)) 语文 from studentscores st.是不是就只选择语文了,呵呵
- SELECT st.NAME 姓名,
- SUM(DECODE(st.object,'语文',st.score,0)) 语文,
- SUM(DECODE(st.object,'数学',st.score,0)) 数学,
- SUM(DECODE(st.object,'英语',st.score,0)) 英语
- FROM studentscores st
- GROUP BY st.NAME ;
现在要求这样的显示格式:
多行转成一列的字符串,这让我们很容易想到oralce中的wm_concat函数的使用
- SELECT st.name , wm_concat(st.object || '(' || st.score || ')')
- FROM studentscores st
- GROUP BY st.name;
- SELECT regexp_substr(t.str,'[^,]+',1,ROWNUM) VALUE
- FROM(SELECT 'a,b,c,d' str FROM dual) t
- CONNECT BY ROWNUM <= LENGTH(regexp_replace(t.str,'[^,]+'))+1;
需求效果图:
方法一
- WITH t1 AS(
- SELECT st.NAME 姓名,
- SUM(DECODE(st.object,'语文',st.score,0)) 语文,
- SUM(DECODE(st.object,'数学',st.score,0)) 数学,
- SUM(DECODE(st.object,'英语',st.score,0)) 英语
- FROM studentscores st
- GROUP BY st.NAME
- ORDER BY st.name DESC
- ),
- t2 AS(
- SELECT '合计' 姓名,
- SUM(DECODE(st.object,'语文',st.score,0)) 语文,
- SUM(DECODE(st.object,'数学',st.score,0)) 数学,
- SUM(DECODE(st.object,'英语',st.score,0)) 英语
- FROM studentscores st
- )
- SELECT t1.*
- FROM t1
- UNION ALL
- SELECT t2.*
- FROM t2
使用方法一体现不出高手风范,来看看方法二
方法二
- SELECT decode(grouping(st.NAME),1,'总计',st.name) 姓名,
- SUM(DECODE(st.object,'语文',st.score,0)) 语文,
- SUM(DECODE(st.object,'数学',st.score,0)) 数学,
- SUM(DECODE(st.object,'英语',st.score,0)) 英语
- FROM studentscores st
- GROUP BY ROLLUP(st.NAME)
- ORDER BY st.name
这需要你先弄明白rollup,grouping是干嘛的才行,具体细节可参考我的另一篇博文oralce之rollup&grouping
在这简单说说,group by rollup(st.name)<=>
select * from xxx group by st.name
union all
select * from xxx
就像方法一那样,先group by st.name得到t1,然后不需要group by求总的得到t2。
GROUPING函数可以接受一列,该列必须是group by中出现的,返回0或者1。如果列值为空,那么GROUPING()返回1;如果列值非空,那么返回0。
效果图如下:
学习了上面的行转列之后,也许你马上就想到这样子来
方法一:
- WITH st AS(
- SELECT st1.name,st1.object,st1.score
- FROM studentscores st1
- UNION ALL
- SELECT st2.name,'总计',SUM(st2.score)
- FROM studentscores st2
- GROUP BY st2.name
- )
- SELECT st.NAME 姓名,
- SUM(DECODE(st.object,'语文',st.score,0)) 语文,
- SUM(DECODE(st.object,'数学',st.score,0)) 数学,
- SUM(DECODE(st.object,'英语',st.score,0)) 英语,
- SUM(DECODE(st.object,'总计',st.score,0)) 总计
- FROM st
- GROUP BY st.NAME ;
嗯,这样也是不失为一张方法,但是也不用这么麻烦
方法二
- SELECT st.NAME 姓名,
- SUM(DECODE(st.object,'语文',st.score,0)) 语文,
- SUM(DECODE(st.object,'数学',st.score,0)) 数学,
- SUM(DECODE(st.object,'英语',st.score,0)) 英语,
- SUM(st.score) 总计
- FROM studentscores st
- GROUP BY st.NAME ;
- SELECT decode(grouping(st.NAME),1,'总计',st.name) 姓名,
- SUM(DECODE(st.object,'语文',st.score,0)) 语文,
- SUM(DECODE(st.object,'数学',st.score,0)) 数学,
- SUM(DECODE(st.object,'英语',st.score,0)) 英语,
- SUM(st.score) 合计
- FROM studentscores st
- GROUP BY ROLLUP(st.NAME)
- ORDER BY st.name
一些报表有些需要更复杂,比如每一种分类都有一个小计,最后再来一个合计,这个可学习我的另一篇博文
oracle之rollup&cube&grouping