时间 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. CF 949 D Curfew —— 二分答案

    题目:http://codeforces.com/contest/949/problem/D 先二分一个答案,让两边都至少满足这个答案: 由于越靠中间的房间越容易满足(被检查的时间靠后),所以策略就是 ...

  2. Tomcat相关的LNMT和LAMT

    Tomcat相关的LNMT和LAMT LNMT:Linux Nginx MySQL Tomcat Client (http) --> nginx (reverse proxy)(http) -- ...

  3. 工作日记:C#获取操作系统、MAC地址、登录用户、网卡、物理内存信息

    /// <summary> /// 操作系统的登录用户名 /// </summary> /// <returns>系统的登录用户名</returns> ...

  4. Educational Codeforces Round 19 E. Array Queries(暴力)(DP)

    传送门 题意 给出n个数,q个询问,每个询问有两个数p,k,询问p+k+a[p]操作几次后超过n 分析 分块处理,在k<sqrt(n)时,用dp,大于sqrt(n)用暴力 trick 代码 #i ...

  5. bzoj 2304: [Apio2011]寻路【spfa】

    我是智障*3,读优写错了调了半天没发现= = 虽然是个最短路却有网络流一般的神建图啊. 首先发现在拐角处转弯是最优的,于是先离散化,然后矩形的四个顶点向距离它最近的上下左右点连边,跑spfa即可. 就 ...

  6. bind:Address alreasy is use

    在bind邦定时,通常会出现bind:Address alreasy is use错误. 此错误可以用setsockopt函数避免 int setsockopt(int sockfd,int leve ...

  7. php安装的扩展php -m可以看到,但是phpinfo()看不到,php-fpm关闭了重新打开还是不行?

    问答 问答详情   php安装的扩展php -m可以看到,但是phpinfo()看不到,php-fpm关闭了重新打开还是不行? centos apache linux html php 3.2k 次浏 ...

  8. Spring 中 ApplicationContext 和 BeanFactory 的区别

    //从ApplicationContext 中取 bean ApplicationContext ac = new ClassPathXmlApplicationContext ( "com ...

  9. GDI+ 加载PNG图片

    #include <GdiPlus.h>#pragma comment(lib, "GdiPlus.lib")using namespace Gdiplus; clas ...

  10. 数据结构 - 静态顺序线性表的实行(C语言)

    数据结构 - 静态顺序线性表的实行(C语言) 1 获取元素操作 对于线性表的顺序存储结构来说,如果我们要实现GetElem操作,即将线性表L中的第i个位置元素值返回,其实是非常简单的. 只要i的数值在 ...