原文为MySQL 5.7 官方手册:12.20.2 GROUP BY Modifiers

一、ROLLUP 修饰符的意义

  GROUP BY子句允许添加WITH ROLLUP修饰符,该修饰符可以对分组后各组的某个列的结果值进行汇总,并在结果中输出,即提供更高一级的聚合操作。

  因此,ROLLUP使您能够使用单个查询在多个分析级别回答问题。例如,ROLLUP可用于为OLAP(在线分析处理)操作提供支持。

  现在有一个示例销售表如下:

CREATE TABLE sales
(
year INT,
country VARCHAR(20),
product VARCHAR(32),
profit INT
);

  先通过以下的分组查询了解下该销售表的数据:

SELECT year, country, product, SUM(profit) AS profit
FROM sales
GROUP BY year, country, product;

  结果:

  按年份分组后,展示利润:

SELECT year, SUM(profit) AS profit
FROM sales
GROUP BY year; /*结果*/
/*
+------+--------+
| year | profit |
+------+--------+
| 2000 | 4525 |
| 2001 | 3010 |
+------+--------+
*/

  现在要想获得所有年份的利润加起来的总利润,只能在此基础上再运行一个查询。而ROLLUP修饰符就是为此而生的,在单个查询上对数据进行不同级别的聚合操作。

  在GROUP BY子句添加WITH ROLLUP后,查询结果会添加一个高级别的聚合行,显示所有奶奶分的利润总和:

SELECT year, SUM(profit) AS profit
FROM sales
GROUP BY year WITH ROLLUP; /*结果*/
/*
+------+--------+
| year | profit|
+------+--------+
| 2000 | 4525 |
| 2001 | 3010 |
| NULL | 7535 |
+------+--------+
*/

  year字段下的null代表高级别的聚合行。

二、多字段分组时ROLLUP的用法

  当对表中多个字段进行分组时,ROLLUP会有更复杂的高级别聚合操作。

  这种情况下,当GROUP BY后字段中,除最后一个字段外的任一字段的值将要发生改变时,MySQL就会产生一个高级别的聚合(汇总)行。

  例如,对上面的第一个分组查询添加“WITH ROLLUP”:

SELECT year, country, product, SUM(profit) AS profit
FROM sales
GROUP BY year, country, product WITH ROLLUP;

  结果如下:

  按照之前所提到的规则,应该是:每当year和country列的值有变动时,就会产生一个高级别的汇总行。

  上面的结果有四种级别的销售数据:

  • 某一年在某个国家单个产品的销售利润(没有ROLLUP的数据)
  • 某一年在某个国家所有产品的总销售利润(例如2000年在芬兰的总利润为1600)
  • 某一年在所有国家的总销售利润(2000年,全球的利润为4525)
  • 所有年份的利润总和(2000,2001两年的总利润为7535)

三、高级聚合行中的NULL值

  MySQL服务器把高级聚合行发送到MySQL客户端时,将会生成每个高级聚合行中的NULL指示符。

  

  因为高级聚合行中的NULL值是在查询处理的后期阶段被放入结果集中,所以开发者只能在select或者having子句中将它们作为null值进行测试。你无法您无法在连接条件或WHERE子句中将它们作为NULL值进行测试,开确定要选择的行。例如,开发者不能在查询中添加“where product is null”来消除掉高级聚合行之外的行。

  那么该如何区分一个列中的NULL值是高级聚合行中的null呢?即怎么筛选出高级聚合行,返回高级聚合信息。MySQL 8.0中提供了grouping(field)函数来区分它们。当某一行的null值属于MySQL为高级聚合行生成的NULL值时,就返回1。我们就可以据此对这些NULL值进行重命名。详情参考MySQL 8.0官方手册——GROUPING()

  

四、在使用ROLLUP时的其它事项

  4.1 当使用ROLLUP时,不能同时使用ORDER BY对结果集进行排序。

  即在MySQL中,ROLLUP和ORDER BY是互斥的,当然可以通过变通的方式来同时实现他们,即将分组结果集生成为派生表,应用order by。例如:

SELECT *
FROM(SELECT year, SUM(profit) AS profit
FROM sales GROUP BY year WITH ROLLUP) AS dt
ORDER BY year DESC;

五、LIMIT与ROLLUP

  LIMIT可以限定返回给MySQL客户端的行的数量。

  若在ROLLUP后面应用LIMIT,因而此时的数量限制也同样适用于通过ROLLUP添加的额外的行。(即高级聚合行没有特权)

  例如:

SELECT year, country, product, SUM(profit) AS profit
FROM sales
GROUP BY year, country, product WITH ROLLUP
LIMIT 5; /* +------+---------+------------+--------+
| year | country | product | profit |
+------+---------+------------+--------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | Finland | NULL | 1600 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
+------+---------+------------+--------+ */

  这种情况容易让人迷惑,无法有效识别出高级聚合行。

六、MySQL的ONLY_FULL_GROUP_BY模式

  该模式由系统变量sql_model控制。

  当sql_model='ONLY_FULL_GROUP_BY'时,在select中出现未在Group By后进行分组的字段时,服务器会拒绝这种查询。

  显然默认情况下,并未开启这种模式,即我们可以在select中直接指定未被进行分组的字段。这种状况下,在这种情况下,服务器可以自由选择摘要行中此非聚合列的任何值,这包括WITH ROLLUP添加的额外行。

  如下所示,country是未被执行分组操作的字段,而从该字段返回的值是不确定的。(但是在这里展示country除了困惑人又有什么意义呢?)

SELECT year, country, SUM(profit) AS profit
FROM sales
GROUP BY year WITH ROLLUP; /* +------+---------+--------+
| year | country | profit |
+------+---------+--------+
| 2000 | India | 4525 |
| 2001 | USA | 3010 |
| NULL | USA | 7535 |
+------+---------+--------+ */

  更让人困惑的是,在“ONLY_FULL_GROUP_BY”模式下, MySQL提供了ANY_VALUE()函数来执行上述操作(返回未被聚合列的任意一个值)。

  下一节会对这种情况有专门的阐述。

MySQL 聚合函数(二)Group By的修饰符——ROLLUP的更多相关文章

  1. 选择列表中的列无效,因为该列没有包含在聚合函数或 GROUP BY 子句中

    选择列表中的列无效,因为该列没有包含在聚合函数或 GROUP BY 子句中 T-SQL核心语句形式: SELECT     --指定要选择的列或行及其限定  [INTO ]      --INTO子句 ...

  2. MySQL聚合函数、控制流程函数(含navicat软件的介绍)

    MySQL聚合函数.控制流程函数(含navicat软件的介绍) 一.navicat的引入:(第三方可视化的客户端,方便MySQL数据库的管理和维护) NavicatTM是一套快速.可靠并价格相宜的数据 ...

  3. 第08章 MySQL聚合函数

    第08章 MySQL聚合函数 我们上一章讲到了 SQL 单行函数.实际上 SQL 函数还有一类,叫做聚合(或聚集.分组)函数,它是对一组数据进行汇总的函数,输入的是一组数据的集合,输出的是单个值. 1 ...

  4. 选择列表中的列……无效,因为该列没有包含在聚合函数或 GROUP BY 子句中

    今天用SQL Server尝试实现一个SQL语句的时候,报了如标题所示的错误,通过在百度里面搜索,并亲自动手实现,终于发现问题所在,现在把它记录下来. 语句如下: select [OrderID],[ ...

  5. mysql 数据操作 单表查询 group by 聚合函数 没有group by情况下

    聚合函数只能用在组里使用 #没有group by 则默认算作一组 取出所有员工的最高工资 mysql> select max(salary) from employee; +---------- ...

  6. MySQL 聚合函数(三)MySQL对GROUP BY的处理

    原文来自MySQL 5.7 官方手册:12.20.3 MySQL Handling of GROUP BY SQL-92和更早版本不允许SELECT列表,HAVING条件或ORDER BY列表引用未在 ...

  7. mysql之聚合函数、group by、having

    sql中提供聚合函数可以用来统计,求和,求最值等 那么聚合函数有哪些呢? COUNT    统计行数量 SUM         求某一列的和 AVG          求某一列的平均值 MAX  求某 ...

  8. MySQL 聚合函数(一)聚合(组合)函数概述

    MySQL版本:5.7+ 本节介绍对值的集合进行操作的组合(聚合)函数.翻译自:Aggregate (GROUP BY) Function Descriptions 一.MySQL 5.7中的聚合函数 ...

  9. mysql聚合函数和分组

    文章实例的数据表,来自上一篇博客<mysql简单查询>:http://blog.csdn.net/zuiwuyuan/article/details/39349611 一. 聚合函数 聚合 ...

随机推荐

  1. [Oracle]关于回滚段的一些转贴摘录

    ORACLE 回滚段 回滚段概述 回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值).回滚段的头部包含正在使用的该回滚段事务的信息.一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段 ...

  2. Web Service 实例基于Socket创建Web服务

    ServerSocket服务器端代码如下: public static void main(String[] args) throws IOException { // 1:建立服务器端的tcp so ...

  3. JAVA 基础编程练习题25 【程序 25 求回文数】

    25 [程序 25 求回文数] 题目:一个 5 位数,判断它是不是回文数.即 12321 是回文数,个位与万位相同,十位与千位相同. package cskaoyan; public class cs ...

  4. 关于CAShapeLayer的一些基本操作

    设置圆形进度条: 实现效果如下: 实现代码如下:(注释很详细啦!!!) UIView *circleView = [[UIView alloc]initWithFrame:CGRectMake(, , ...

  5. 文件夹中含有子文件夹,修改子文件夹中的图像存储格式(python实现)

    文件夹中含有子文件夹,修改子文件夹中的图像存储格式,把png图像改为jpg图像,python代码如下: import os import cv2 filePath = 'C:\\Users\\admi ...

  6. C语言tips_2 关于scanf 读取规则小结以及与getchar 的区别

    第一点:scanf默认回车和空格是输入不同组之间的间隔和结束符号. 也就是说他不会读取 空格 和 换行符.而是把他们当作一个 数据被读取完成的标志!他的停止标志则为,当%d之类的数据输入结束之后,自动 ...

  7. python列表删除--remove(),del,pop()

    remove()参数为列表元素,若在列表中,删除,不在则报错 如: pop()不带参数时默认删除列表的末尾元素并返回该元素,带参数时该参数为列表元素的下标值 不带参数: 以下标为参数: del 后面可 ...

  8. python列表插入--append(), extend(), insert()

    append(),extend(), insert()都是列表操作中常用的插入函数.其中前两个均接收一个参数,并插入到列表尾部.最后一个接收两个参数,将参数2插入到参数1之前. 本文主要讨论appen ...

  9. 【Python】机器学习之单变量线性回归 利用正规方程找到合适的参数值

    [Python]机器学习之单变量线性回归 利用正规方程找到合适的参数值 本次作业来自吴恩达机器学习. 你是一个餐厅的老板,你想在其他城市开分店,所以你得到了一些数据(数据在本文最下方),数据中包括不同 ...

  10. Ubuntu 18.04 更换阿里源

    1.备份 sudo cp /etc/apt/source.list /etc/apa/source.list.bak 2.编辑 sudo vim /etc/apt/source.list 3.修改内容 ...