Mysql,Oracle使用rollup函数完成行列统计
昨天突然在 一篇博客中看到了Mysql也有rollup函数,原博文使用了rollup进行行列统计,原博文链接如下:
http://www.cnblogs.com/lhj588/archive/2012/06/15/2550392.html
本博文主要是记录下mysql和oracle使用rollup函数进行行列统计,内容比较简单。
首先是mysql,建表测试:
CREATE TABLE `tmysql_test_hanglietongji` (
`id` int(11) NOT NULL,
`c1` char(2) COLLATE utf8_bin DEFAULT NULL,
`c2` char(2) COLLATE utf8_bin DEFAULT NULL,
`c3` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
INSERT INTO `tmysql_test_hanglietongji` VALUES (1, 'A1', 'B1', 9);
INSERT INTO `tmysql_test_hanglietongji` VALUES (2, 'A2', 'B1', 7);
INSERT INTO `tmysql_test_hanglietongji` VALUES (3, 'A3', 'B1', 4);
INSERT INTO `tmysql_test_hanglietongji` VALUES (4, 'A4', 'B1', 2);
INSERT INTO `tmysql_test_hanglietongji` VALUES (5, 'A1', 'B2', 2);
INSERT INTO `tmysql_test_hanglietongji` VALUES (6, 'A2', 'B2', 9);
INSERT INTO `tmysql_test_hanglietongji` VALUES (7, 'A3', 'B2', 8);
INSERT INTO `tmysql_test_hanglietongji` VALUES (8, 'A4', 'B2', 5);
INSERT INTO `tmysql_test_hanglietongji` VALUES (9, 'A1', 'B3', 1);
INSERT INTO `tmysql_test_hanglietongji` VALUES (10, 'A2', 'B3', 8);
INSERT INTO `tmysql_test_hanglietongji` VALUES (11, 'A3', 'B3', 8);
INSERT INTO `tmysql_test_hanglietongji` VALUES (12, 'A4', 'B3', 6);
INSERT INTO `tmysql_test_hanglietongji` VALUES (13, 'A1', 'B4', 8);
INSERT INTO `tmysql_test_hanglietongji` VALUES (14, 'A2', 'B4', 2);
INSERT INTO `tmysql_test_hanglietongji` VALUES (15, 'A3', 'B4', 6);
INSERT INTO `tmysql_test_hanglietongji` VALUES (16, 'A4', 'B4', 9);
INSERT INTO `tmysql_test_hanglietongji` VALUES (17, 'A1', 'B4', 3);
INSERT INTO `tmysql_test_hanglietongji` VALUES (18, 'A2', 'B4', 5);
INSERT INTO `tmysql_test_hanglietongji` VALUES (19, 'A3', 'B4', 2);
INSERT INTO `tmysql_test_hanglietongji` VALUES (20, 'A4', 'B4', 5);
要完成的效果如下:
最简单的是使用union,如下:
select ifnull(c1, 'total') as 'total',
sum(if(c2 = 'B1', C3, 0)) AS B1,
sum(if(c2 = 'B2', C3, 0)) AS B2,
sum(if(c2 = 'B3', C3, 0)) AS B3,
sum(if(c2 = 'B4', C3, 0)) AS B4,
SUM(C3) AS TOTAL
from tmysql_test_hanglietongji
group by C1
union
select 'total' as 'total',
sum(if(c2 = 'B1', C3, 0)) AS B1,
sum(if(c2 = 'B2', C3, 0)) AS B2,
sum(if(c2 = 'B3', C3, 0)) AS B3,
sum(if(c2 = 'B4', C3, 0)) AS B4,
SUM(C3) AS TOTAL
from tmysql_test_hanglietongji
order by 1
也可以使用with rollup函数。注意当使用 rollup时, 你不能同时使用 order by子句进行结果排序
select ifnull(c1, 'total') 'total',
sum(if(c2 = 'B1', C3, 0)) AS B1,
sum(if(c2 = 'B2', C3, 0)) AS B2,
sum(if(c2 = 'B3', C3, 0)) AS B3,
sum(if(c2 = 'B4', C3, 0)) AS B4,
SUM(C3) AS TOTAL
from tmysql_test_hanglietongji
group by C1 with rollup;
with rollup其实是第一个的简化。
也可以这样写:
SELECT IFNULL(c1, 'total') AS total,
SUM(IF(c2 = 'B1', c3, 0)) AS B1,
SUM(IF(c2 = 'B2', c3, 0)) AS B2,
SUM(IF(c2 = 'B3', c3, 0)) AS B3,
SUM(IF(c2 = 'B4', c3, 0)) AS B4,
SUM(IF(c2 = 'total', c3, 0)) AS total
FROM (SELECT c1, IFNULL(c2, 'total') AS c2, SUM(c3) AS c3
FROM tmysql_test_hanglietongji
GROUP BY c1, c2 WITH ROLLUP
HAVING c1 IS NOT NULL) AS A
GROUP BY c1 WITH ROLLUP;
HAVING c1 IS NOT NULL条件主要是过滤掉对整个tmysql_test_hanglietongji 表求和的那一行,以上面的子查询为例:
SELECT c1, IFNULL(c2, 'total') AS c2, SUM(c3) AS c3
FROM tmysql_test_hanglietongji
GROUP BY c1, c2 WITH ROLLUP
结果是:
相当于:
SELECT c1, IFNULL(c2, 'total') AS c2, SUM(c3) AS c3
FROM tmysql_test_hanglietongji
GROUP BY c1, c2
union ALL
SELECT c1, 'total' AS c2, SUM(c3) AS c3
FROM tmysql_test_hanglietongji
GROUP BY c1
union ALL
SELECT NULL, 'total' AS c2, SUM(c3) AS c3
FROM tmysql_test_hanglietongji
结果是:
可以看出group by c1,c2 with rollup相当于group by c1,c2 union group by c1(c2替换为NULL) union (c1,c2全部替换为NULL)。
这里的替换规则参考了链接
http://blog.itpub.net/519536/viewspace-610995
原文是替换Oracle的rollup,在Mysql中也适用。
使用普通sql写法是:
SELECT IFNULL(c1, 'total') AS total,
SUM(IF(c2 = 'B1', c3, 0)) AS B1,
SUM(IF(c2 = 'B2', c3, 0)) AS B2,
SUM(IF(c2 = 'B3', c3, 0)) AS B3,
SUM(IF(c2 = 'B4', c3, 0)) AS B4,
SUM(IF(c2 = 'total', c3, 0)) AS total
FROM (SELECT c1, IFNULL(c2, 'total') AS c2, SUM(c3) AS c3
FROM tmysql_test_hanglietongji
GROUP BY c1, c2
HAVING c1 IS NOT NULL
union
SELECT c1, 'total' as c2, SUM(c3) AS c3
FROM tmysql_test_hanglietongji
group by c1) A
group by c1
UNION
SELECT 'total' as total,
SUM(IF(c2 = 'B1', c3, 0)) AS B1,
SUM(IF(c2 = 'B2', c3, 0)) AS B2,
SUM(IF(c2 = 'B3', c3, 0)) AS B3,
SUM(IF(c2 = 'B4', c3, 0)) AS B4,
SUM(IF(c2 = 'total', c3, 0)) AS total
FROM (SELECT c1, IFNULL(c2, 'total') AS c2, SUM(c3) AS c3
FROM tmysql_test_hanglietongji
GROUP BY c1, c2
HAVING c1 IS NOT NULL
union
SELECT c1, 'total' as c2, SUM(c3) AS c3
FROM tmysql_test_hanglietongji
group by c1) A
少了一个是因为上面的having要求c1 is not null,所以替换c1为NULL就没有了。
下面看下oracle中怎么写,想要的效果如图:
首先建表。
create table TSQL_TEST_HANGLIETONGJI
(
ID NUMBER(4) not null,
C1 VARCHAR2(2),
C2 VARCHAR2(2),
C3 NUMBER(4)
)
;
alter table TSQL_TEST_HANGLIETONGJI
add primary key (ID); insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (1, 'A1', 'B1', 9);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (2, 'A2', 'B1', 7);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (3, 'A3', 'B1', 4);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (4, 'A4', 'B1', 2);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (5, 'A1', 'B2', 2);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (6, 'A2', 'B2', 9);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (7, 'A3', 'B2', 8);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (8, 'A4', 'B2', 5);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (9, 'A1', 'B3', 1);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (10, 'A2', 'B3', 8);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (11, 'A3', 'B3', 8);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (12, 'A4', 'B3', 6);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (13, 'A1', 'B4', 8);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (14, 'A2', 'B4', 2);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (15, 'A3', 'B4', 6);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (16, 'A4', 'B4', 9);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (17, 'A1', 'B4', 3);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (18, 'A2', 'B4', 5);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (19, 'A3', 'B4', 2);
insert into TSQL_TEST_HANGLIETONGJI (ID, C1, C2, C3)
values (20, 'A4', 'B4', 5);
最简单的写法是:
select c1,
sum(decode(c2,'B1', C3, 0)) AS B1,
sum(decode(c2 ,'B2', C3, 0)) AS B2,
sum(decode(c2 ,'B3', C3, 0)) AS B3,
sum(decode(c2 ,'B4', C3, 0)) AS B4,
SUM(C3) AS TOTAL
from tsql_test_hanglietongji
group by C1
UNION
SELECT 'TOTAL',
sum(decode(c2 ,'B1', C3, 0)) AS B1,
sum(decode(c2 ,'B2', C3, 0)) AS B2,
sum(decode(c2 ,'B3', C3, 0)) AS B3,
sum(decode(c2 ,'B4', C3, 0)) AS B4,
SUM(C3)
FROM tsql_test_hanglietongji
然后使用rollup函数简化。
SELECT nvl(c1, 'total') AS total,
SUM(decode(c2, 'B1', c3, 0)) AS B1,
SUM(decode(c2, 'B2', c3, 0)) AS B2,
SUM(decode(c2, 'B3', c3, 0)) AS B3,
SUM(decode(c2, 'B4', c3, 0)) AS B4,
sum(c3) AS total
FROM tsql_test_hanglietongji
GROUP BY ROLLUP(c1)
也可以这么写:
SELECT nvl(c1, 'total') AS total_c,
SUM(decode(c2, 'B1', c3, 0)) AS B1,
SUM(decode(c2, 'B2', c3, 0)) AS B2,
SUM(decode(c2, 'B3', c3, 0)) AS B3,
SUM(decode(c2, 'B4', c3, 0)) AS B4,
SUM(decode(c2, 'total', c3, 0)) AS total_r
FROM (SELECT c1, nvl(c2, 'total') AS c2, SUM(c3) AS c3
FROM tsql_test_hanglietongji
GROUP BY ROLLUP(c1, c2)
HAVING c1 IS NOT NULL) A
GROUP BY ROLLUP(c1);
rollup和普通sql替换上面也说了,举个例子:
SELECT c1, nvl(c2, 'total') AS c2, SUM(c3) AS c3
FROM tsql_test_hanglietongji
GROUP BY ROLLUP(c1, c2)
效果是:
普通sql写法是:
SELECT c1, nvl(c2, 'total') AS c2, SUM(c3) AS c3
FROM tsql_test_hanglietongji
GROUP BY c1, c2
union all
SELECT c1, nvl(null, 'total') AS c2, SUM(c3) AS c3
FROM tsql_test_hanglietongji
GROUP BY c1
union all
SELECT NULL, 'total' AS c2, SUM(c3) AS c3
FROM tsql_test_hanglietongji
order by 1, 2
细心的朋友也许注意到了,第二个union all带了order by 1,2而上面的mysql没有带order by,这和mysql和oracle对NULL的默认排序规则有关。
使用普通sql重写rollup为:
SELECT nvl(c1, 'total') AS total_c,
SUM(decode(c2, 'B1', c3, 0)) AS B1,
SUM(decode(c2, 'B2', c3, 0)) AS B2,
SUM(decode(c2, 'B3', c3, 0)) AS B3,
SUM(decode(c2, 'B4', c3, 0)) AS B4,
SUM(decode(c2, 'total', c3, 0)) AS total_r
FROM (SELECT c1, nvl(c2, 'total') AS c2, SUM(c3) AS c3
FROM tsql_test_hanglietongji
GROUP BY c1, c2
HAVING c1 IS NOT NULL
union all
SELECT c1, nvl(null, 'total') AS c2, SUM(c3) AS c3
FROM tsql_test_hanglietongji
GROUP BY c1
HAVING c1 IS NOT NULL) A
GROUP BY c1
union all
SELECT nvl(null, 'total') AS total_c,
SUM(decode(c2, 'B1', c3, 0)) AS B1,
SUM(decode(c2, 'B2', c3, 0)) AS B2,
SUM(decode(c2, 'B3', c3, 0)) AS B3,
SUM(decode(c2, 'B4', c3, 0)) AS B4,
SUM(decode(c2, 'total', c3, 0)) AS total_r
FROM (SELECT c1, nvl(c2, 'total') AS c2, SUM(c3) AS c3
FROM tsql_test_hanglietongji
GROUP BY c1, c2
HAVING c1 IS NOT NULL
union all
SELECT c1, nvl(null, 'total') AS c2, SUM(c3) AS c3
FROM tsql_test_hanglietongji
GROUP BY c1
HAVING c1 IS NOT NULL) A
order by 1
这里也排除了c1 is null的情况。
通过上面的对比,发现oracle和mysql的rollup非常相似,对rollup函数感兴趣的朋友请仔细搜索rollup学习。
到这里该结束了,有任何意见请留言,如文中sql有错误也请指出,谢谢。
Mysql,Oracle使用rollup函数完成行列统计的更多相关文章
- 24、jQuery常用AJAX-API/Java调用MySQL / Oracle过程与函数
1)掌握jQuery常用AJAX-API 2)掌握Java调用MySQL / Oracle过程与函数 一)jQuery常用AJAX-API 目的:简化客户端与服务端进行局部刷新的异步通讯 (1)取 ...
- 【Oracle】rollup函数
当我们在做报表统计的时候,很多时候需要用到‘合计’这个功能,比如我们想得到如下格式的报表: 这张表是按照deptno分组,然后按照deptno分组合计.rollup函数可以完美的解决这个问题. 1.建 ...
- mysql的with rollup
无意间发现了mysql的with rollup函数(用在group by 函数后面) 测试 1. SELECT NAME,DATE,score FROM stu 结果是 2. SELECT NAME, ...
- Atitit 数据库 标准库 sdk 函数库 编程语言 mysql oracle attilax总结
Atitit 数据库 标准库 sdk 函数库 编程语言 mysql oracle attilax总结 1.1. 常见的编程语言以及数据库 sql内部函数库标准化库一般有以下api1 1.2. 各个 ...
- oracle和mysql功能相同的函数
wm_concat ---->mysql 的group_concat decode (两条件的)----->mysql 的 if decode (3个及以上条件的)---------> ...
- Oracle的聚合函数group by结合CUBE和ROLLUP的使用
转自:https://docs.oracle.com/cd/E11882_01/server.112/e25554/aggreg.htm#DWHSG8618 CUBE Syntax CUBE appe ...
- ORACLE rollup函数
rollup函数应用场景: 主要使用在 分组中,将每个分组求汇总值(就是小计),最后再讲所有值(除去小计)求和(就是合计) 当然,使用union 也可以达到同样的效果.先将需要查询的分组查出来,再un ...
- MySQL如何使用WITH ROLLUP函数
一.WITH ROLLUP函数适用于跟在GROUP BY 字段后面进行分组求和使用 SELECT t1.`产品名称`,SUM(t1.`数量`),SUM(t1.`金额`),t1.`日期` FROM sh ...
- Oracle用法、函数备忘记录
Listagg select * from emp select LISTAGG(ename,'-') within group (order by deptno desc) from emp; 可以 ...
随机推荐
- 解决weblogic页面和控制台乱码问题
转自:https://blog.csdn.net/u010995831/article/details/53283746 之前一直有碰到weblogic各种乱码问题,要不就是页面乱码,要不就是控制台乱 ...
- Vue解决安卓4.4不兼容的问题
1.npm安装 npm install babel-polyfillnpm install es6-promise package.json中会出现 "babel-polyfill" ...
- Linux 平台下阅读源码的工具链
原文:http://blog.jobbole.com/101322/ 前言 看源代码是一个程序员必须经历的事情,也是可以提升能力的一个捷径.个人认为: 要完全掌握一个软件的方法只有阅读源码. 在Win ...
- java.util.Optional
public class OptionalDemo { public static void main(String[] args) { //创建Optional实例,也可以通过方法返回值得到. Op ...
- MySQL之不得不说的keepsync和trysync
此文已由作者温正湖授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 开宗明义,keepsync和trysync是网易MySQL分支版本InnoSQL的两个参数,非常重要的两个参 ...
- bzoj 1923: [Sdoi2010]外星千足虫【高斯消元】
裸的异或高斯消元 #include<iostream> #include<cstdio> using namespace std; const int N=2005; int ...
- 大水题(water)
题目描述dzy 定义一个 $n^2$ 位的数的生成矩阵 $A$ 为一个大小为 $n \times n$ 且 Aij 为这个数的第 $i \times n+j-n$ 位的矩阵.现在 dzy 有一个数 $ ...
- Golang 在 Linux CentOS 6.5 服务器上实现 博客后台程序开机启动
在linux下想实现开机启动的方法很多,这里我采用了在/etc/rc.local里写shell指令的方式. 以下就以我的实际操作为例子讲述,很多地方需要看官自己调整信息哦! 1.在/etc/rc.lo ...
- cxf CXF搭建webService服务器
http://observer.blog.51cto.com/4267416/1231205 手动发布: public class ServerMain { public static void ma ...
- Qt事件系统之一:Qt中的事件处理与传递
一.简介 在Qt中,事件作为一个对象,继承自 QEvent 类,常见的有键盘事件 QKeyEvent.鼠标事件 QMouseEvent 和定时器事件 QTimerEvent 等,与 QEvent 类的 ...