时间 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. body和html

    1 关于html和body的背景颜色的一些变现 当给body设置背景颜色时(html没有背景颜色),这时body被当做根节点被浏览器俘获,浏览器界面的背景颜色就为body的background颜色:当 ...

  2. Pascal之while

    program Project1; {$APPTYPE CONSOLE} uses SysUtils; begin { TODO -oUser -cConsole Main : Insert code ...

  3. Swift4 协议

    创建: 2018/02/27 完成: 2018/02/28 更新: 2018/03/07 增加类采用协议时的注意 补充只有类, 结构体, 枚举型可以采用协议 增加为类定义准备的协议( protocol ...

  4. Phpstorm安装和优化

    Phpstorm是php开发一个强大的IDE,但是它不是免费的需要注册码,而且界面是英文界面,对英文不太好的人有点不友好.所以这篇文章主要从phpstorm的破解和汉化来优化phpstorm. 1.首 ...

  5. 矩阵快速幂/矩阵加速线性数列 By cellur925

    讲快速幂的时候就提到矩阵快速幂了啊,知道是个好东西,但是因为当时太蒟(现在依然)没听懂.现在把它补上. 一.矩阵快速幂 首先我们来说说矩阵.在计算机中,矩阵通常都是用二维数组来存的.矩阵加减法比较简单 ...

  6. 暑期训练狂刷系列——Hdu 1698 Just a Hook (线段树区间更新)

    题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=1698 题目大意: 有一个钩子有n条棍子组成,棍子有铜银金三种组成,价值分别为1,2,3.为了对付每场 ...

  7. linux 前台后台程序切换命令总结

    1.在Linux终端运行命令的时候,在命令末尾加上 & 符号,就可以让程序在后台运行 root@Ubuntu$ ./tcpserv01 & 2.如果程序正在前台运行,可以使用 Ctrl ...

  8. 四大开源协议比较:BSD、Apache、GPL、LGPL【转载】

    四大开源协议原文链接 本文参考文献:http://www.fsf.org/licensing/licenses/ 现今存在的开源协议很多,而经过Open Source Initiative组织通过批准 ...

  9. 452 Minimum Number of Arrows to Burst Balloons 用最少数量的箭引爆气球

    在二维空间中有许多球形的气球.对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标.由于它是水平的,所以y坐标并不重要,因此只要知道开始和结束的x坐标就足够了.开始坐标总是小于结束坐标.平面 ...

  10. 静态代理,jdbc动态代理和cglib动态代理

    静态代理 1.定义抽象主题接口. package com.zhangguo.Spring041.aop02; /** * 接口 * 抽象主题 */ public interface IMath { / ...