时间 2014-02-25 00:05:38  ITeye-博客

昨天突然在 一篇博客中看到了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函数完成行列统计的更多相关文章

  1. 24、jQuery常用AJAX-API/Java调用MySQL / Oracle过程与函数

      1)掌握jQuery常用AJAX-API 2)掌握Java调用MySQL / Oracle过程与函数 一)jQuery常用AJAX-API 目的:简化客户端与服务端进行局部刷新的异步通讯 (1)取 ...

  2. 【Oracle】rollup函数

    当我们在做报表统计的时候,很多时候需要用到‘合计’这个功能,比如我们想得到如下格式的报表: 这张表是按照deptno分组,然后按照deptno分组合计.rollup函数可以完美的解决这个问题. 1.建 ...

  3. mysql的with rollup

    无意间发现了mysql的with rollup函数(用在group by 函数后面) 测试 1. SELECT NAME,DATE,score FROM stu 结果是 2. SELECT NAME, ...

  4. Atitit 数据库 标准库  sdk 函数库 编程语言 mysql oracle  attilax总结

    Atitit 数据库 标准库  sdk 函数库 编程语言 mysql oracle  attilax总结 1.1. 常见的编程语言以及数据库 sql内部函数库标准化库一般有以下api1 1.2. 各个 ...

  5. oracle和mysql功能相同的函数

    wm_concat ---->mysql 的group_concat decode (两条件的)----->mysql 的 if decode (3个及以上条件的)---------> ...

  6. Oracle的聚合函数group by结合CUBE和ROLLUP的使用

    转自:https://docs.oracle.com/cd/E11882_01/server.112/e25554/aggreg.htm#DWHSG8618 CUBE Syntax CUBE appe ...

  7. ORACLE rollup函数

    rollup函数应用场景: 主要使用在 分组中,将每个分组求汇总值(就是小计),最后再讲所有值(除去小计)求和(就是合计) 当然,使用union 也可以达到同样的效果.先将需要查询的分组查出来,再un ...

  8. MySQL如何使用WITH ROLLUP函数

    一.WITH ROLLUP函数适用于跟在GROUP BY 字段后面进行分组求和使用 SELECT t1.`产品名称`,SUM(t1.`数量`),SUM(t1.`金额`),t1.`日期` FROM sh ...

  9. Oracle用法、函数备忘记录

    Listagg select * from emp select LISTAGG(ename,'-') within group (order by deptno desc) from emp; 可以 ...

随机推荐

  1. 异常备忘:java.lang.UnsupportedClassVersionError: Bad version number in .class file

    转自:https://blog.csdn.net/myyugioh/article/details/7724915 今天在导入一个工程时,编译并打包到Tomcat后,发现出现java.lang.Uns ...

  2. HDU2262;Where is the canteen(高斯消元+期望)

    传送门 题意 给出一张图,LL从一个点等概率走到上下左右位置,询问LL从宿舍走到餐厅的步数期望 分析 该题是一道高斯消元+期望的题目 难点在于构造矩阵,我们发现以下结论 设某点走到餐厅的期望为Ek 1 ...

  3. 【爬坑系列】之解读kubernetes的认证原理&实践

    对于访问kube-apiserver模块的请求来说,如果是使用http协议,则会顺利进入模块内部得到自己想要的:但是如果是用的是https,则能否进入模块内部获得想要的资源,他会首先要进行https自 ...

  4. Luogu P1638 逛画展 【二分答案】

    题目描述 博览馆正在展出由世上最佳的 M 位画家所画的图画. wangjy想到博览馆去看这几位大师的作品. 可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字, a和b,代表他要看 ...

  5. Canvas 入门案例

    五.  Canvas 入门案例 1.  canvas 圆形绘制 <!DOCTYPE html> <html lang="en"> <head> ...

  6. hdu---------3189-------------------

    水体一个,但是这种做题的方法值得发扬光大............ Just Do It Time Limit: / MS (Java/Others) Memory Limit: / K (Java/O ...

  7. Boost1.6x+win7+VC2015编译

    下载 通过boost官方网站, 或直接在source forge下载boost_1_6x_0. 可选包 Zlib library, 环境变量: ZLIB_SOURCE bzip2, 环境变量: BZI ...

  8. python网络爬虫之二requests模块

    requests http请求库 requests是基于python内置的urllib3来编写的,它比urllib更加方便,特别是在添加headers, post请求,以及cookies的设置上,处理 ...

  9. 暑期训练狂刷系列——Hdu 3506 Largest Rectangle in a Histogram (单调栈)

    题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=1506 题目大意: 给出一个数列An,问以Ai为最小值的区间内有多少个元素? 解题思路: 手动模拟一个 ...

  10. _bzoj3223 Tyvj 1729 文艺平衡树【Splay】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3223 裸的,打个标记. #include <cstdio> #include & ...