五种主流数据库:高级分组

除了基本的分组功能之外,GROUP BY 子句还提供了几个高级选项,可以用来实现更复杂的报表功能。

本文比较五种主流数据库实现的高级分组功能,包括 MySQL、Oracle、SQL Server、PostgreSQL 以及 SQLite。

功能MySQLOracleSQL ServerPostgreSQLSQLite
ROLLUP✔️✔️✔️✔️
CUBE✔️✔️✔️
GROUPING SETS✔️✔️✔️
GROUPING 函数✔️✔️✔️✔️

小计、合计与总计

GROUP BY 子句的 ROLLUP 选项可以生成按照不同层级进行汇总的结果,从而实现报表中的小计、合计和总计。例如:

-- Oracle、Microsoft SQL Server 以及 PostgreSQL
SELECT dept_id AS "部门编号", sex AS "性别", COUNT(*) AS "员工数量"
FROM employee
GROUP BY ROLLUP (dept_id, sex);

其中,ROLLUP 表示首先按照不同部门和性别的组合统计员工数量,然后按照不同的部门统计员工数量,最后统计全体员工的数量,注意括号不能省略。Oracle、Microsoft SQL Server 以及 PostgreSQL 实现了以上语法,查询返回的结果如下:

部门编号|性别|员工数量
------|---|-------1|| 31|   | 32|| 32|   | 33|| 23|   | 24|| 84|| 14|   | 95|| 85|   | 8|   | 25

查询结果中性别为空的记录表示按照不同部门统计的员工数量,部门编号和性别都为空的记录表示全体员工的数量。

MySQL 提供了 ROLLUP 选项,但是语法略有不同。例如:

-- MySQL 和 Microsoft SQL Server
SELECT dept_id AS "部门编号", sex AS "性别", COUNT(*) AS "员工数量"
FROM employee
GROUP BY dept_id, sex WITH ROLLUP;

其中,WITH ROLLUP 位于分组字段之后,而且无须使用括号。查询返回的结果和上面的示例相同。另外,Microsoft SQL Server 也支持这种语法。

提示:GROUP BY 子句的 ROLLUP 选项表示先按照所有分组字段进行分组汇总,然后从右至左依次去掉一个分组字段再进行分组汇总,被去掉的字段显示为空。最后,将所有的数据进行一次汇总,所有分组字段都显示为空。

SQLite 目前不支持 ROLLUP 选项。

交叉统计报表

GROUP BY 子句的 CUBE 选项可以对分组字段进行各种组合,产生类似于 Excel 数据透视表的多维度交叉报表。例如:

-- Oracle、Microsoft SQL Server 以及 PostgreSQL
SELECT dept_id AS "部门编号", sex AS "性别", COUNT(*) AS "员工数量"
FROM employee
GROUP BY CUBE (dept_id, sex);

其中,CUBE 表示首先按照不同部门和性别的组合统计员工数量,然后按照不同的部门统计员工数量,之后按照不同的性别统计员工数量,最后统计全体员工的数量。Oracle、Microsoft SQL Server 以及 PostgreSQL 实现了以上语法,查询返回的结果如下:

部门编号|性别|员工数量
------|---|-------1|| 32|| 34|| 85|| 8|| 223|| 24|| 1|| 3|   | 251|   | 32|   | 33|   | 24|   | 95|   | 8

查询结果中性别为空的记录表示按照不同部门统计的员工数量,部门编号为空的记录表示按照不同性别统计的员工数量,部门编号和性别都为空的记录表示全体员工的数量。

提示:GROUP BY 子句的 CUBE 选项产生的分组情况随着分组字段的增加呈指数级 (2n )增长,ROLLUP选项产生的分组情况随着分组字段的增加呈线性(n+1) 增长。

MySQL 和 SQLite 目前不支持 CUBE 选项。

自定义维度统计

ROLLUP 和 CUBE 选项都是按照固定的方式进行分组,GROUP BY 子句还支持一种更为灵活的分组选项:GROUPING SETS。该选项可以用来指定自定义的分组集,也就是自定义分组字段的组合方式。例如:

GROUP BY dept_id, sex

相当于指定了 1 个分组集:

GROUP BY GROUPING SETS ((dept_id, sex))

其中,(dept_id, sex) 表示按照不同部门和性别的组合进行分组,括号内的所有字段作为一个分组集,最外面的括号则包含了所有的分组集。

同样,以下 ROLLUP 选项:

GROUP BY ROLLUP(dept_id, sex)

相当于指定了 3 个分组集:

GROUP BY GROUPING SETS ((dept_id, sex), (dept_id), ())

其中,(dept_id, sex) 表示按照不同部门和性别的组合进行分组,(dept_id) 表示按照不同的部门进行分组,() 表示对全体员工进行汇总。

同样,以下 CUBE 选项:

GROUP BY CUBE(dept_id, sex)

相当于指定了 4 个分组集:

GROUP BY GROUPING SETS ((dept_id, sex), (dept_id), (sex), ())

其中,(dept_id, sex) 表示按照不同部门和性别的组合进行分组,(dept_id) 表示按照不同的部门进行分组,(sex) 表示按照不同的性别进行分组,() 表示对全体员工进行汇总。

因此,ROLLUP 和 CUBE 选项都属于 GROUPING SETS 选项的特例。GROUPING SETS 选项的优势在于,可以指定任意的分组方式。例如:

-- Oracle、Microsoft SQL Server 以及 PostgreSQL
SELECT dept_id AS "部门编号", sex AS "性别", COUNT(*) AS "员工数量"
FROM employee
GROUP BY GROUPING SETS ((dept_id), (sex), ());

以上查询分别按照不同的部门、不同的性别统计员工的数量,同时统计了全体员工的数量。查询返回的结果如下:

部门编号|性别|员工数量
-------|---|-------|   | 254|   | 92|   | 33|   | 21|   | 35|   | 8|| 22|| 3

当分组统计的维度越来越多时,这种方式可以方便我们实现各种不同的业务统计需求。

MySQL 和 SQLite 目前不支持 GROUPING SETS 选项。

GROUPING 函数

我们在使用 GROUP BY 子句的扩展选项时,查询会产生一些空值数据。这些空值意味着对应的记录是针对这个字段所有数据的汇总,我们可以利用 GROUPING 函数识别这些空值数据。例如:

-- Oracle、Microsoft SQL Server 以及 PostgreSQL
SELECT sex AS "性别", COUNT(*) AS "员工数量",GROUPING(sex) AS "所有性别"
FROM employee
GROUP BY ROLLUP (dept_id, sex);

查询返回的结果如下:

性别|员工数量|所有性别
---|-------|-------|     22| 0|      3| 0|     25| 1

其中,GROUPING(sex) 函数返回 0,表示当前记录不是所有性别的汇总数据;返回 1,表示当前记录是所有性别的汇总数据。因此,结果中的最后一条记录表示全体员工的数量。

我们可以进一步利用 CASE 表达式对查询结果进行转换显示:

-- Oracle、Microsoft SQL Server 以及 PostgreSQL
SELECT CASE GROUPING(sex) WHEN 1 THEN '所有性别' ELSE sex END AS "性别",COUNT(*) AS "员工数量"
FROM employee
GROUP BY ROLLUP (sex);

查询返回的结果如下:

性别   |员工数量
-------|------| 3| 22
所有性别| 25

我们将最后一行中性别为空的数据显示为“所有性别”。

MySQL 同样支持 GROUPING 函数,例如:

-- MySQL 和 Microsoft SQL Server
SELECT CASE GROUPING(sex) WHEN 1 THEN '所有性别' ELSE sex END AS "性别",COUNT(*) AS "员工数量"
FROM employee
GROUP BY sex WITH ROLLUP;

查询返回的结果和上面的示例相同。

SQLite 中的 GROUP BY 子句不支持扩展选项,因此也就没有提供 GROUPING 函数。

案例:销售数据分析

接下来我们将会使用一个虚拟的销售数据集(sales_data)。该数据集包含了 2019 年 1 月 1 日到 2019 年 6 月 30 日三种产品在三个渠道每天的销售情况。示例表的创建脚本可以从图书《SQL编程思想》的配套网站下载,以下是该表中的部分数据:

saledate  |product|channel|amount 
----------|-------|-------|-------
2019-01-01|桔子    |淘宝   |1864.00
2019-01-01|桔子    |京东   |1329.00
2019-01-01|桔子    |店面   |1736.00
2019-01-01|香蕉    |淘宝   |1573.00
2019-01-01|香蕉    |京东   |1364.00
2019-01-01|香蕉    |店面   |1178.00
2019-01-01|苹果    |淘宝   | 511.00
2019-01-01|苹果    |京东   | 568.00
2019-01-01|苹果    |店面   | 847.00
...

我们首先通过分组汇总了解一下产品的整体销售情况:

-- Oracle、Microsoft SQL Server 以及 PostgreSQL
SELECT CASE GROUPING(product) WHEN 1 THEN '所有产品' ELSE product END AS "产品",CASE GROUPING(channel) WHEN 1 THEN '所有渠道' ELSE channel END AS "渠道",SUM(amount) "销售金额"
FROM sales_data
GROUP BY ROLLUP (product, channel)
ORDER BY product, SUM(amount) DESC;

其中,GROUP BY ROLLUP 子句表示统计不同产品不同渠道的销售金额小计、不同产品所有渠道的销售金额合计以及所有产品的销售总计。查询返回的结果如下:

产品   |渠道   |销售金额 
------|-------|---------
桔子   |所有渠道| 909261.00
桔子   |京东   | 311799.00
桔子   |淘宝   | 302782.00
桔子   |店面   | 294680.00
苹果   |所有渠道| 937052.00
苹果   |京东   | 318614.00
苹果   |淘宝   | 311795.00
苹果   |店面   | 306643.00
香蕉   |所有渠道| 925369.00
香蕉   |店面   | 311445.00
香蕉   |淘宝   | 307891.00
香蕉   |京东   | 306033.00
所有产品|所有渠道|2771682.00

在我们的模拟数据中,桔子的销售金额为 909261 元,在京东商城的销量最高,在店面的销量最低;苹果的销售金额为 937052 元,在京东商城的销量最高,在店面的销量最低;香蕉的销售金额为 925369 元,在店面的销量最高,在京东商城的销量最低;所有产品的销售金额总计为 2771682 元。

对于 MySQL,我们可以使用 WITH ROLLUP 选项实现相同的功能。

在 Excel 中有一个分析功能,叫作数据透视表(Pivot Table),数据透视表可以提供不同级别的数据统计、对比分析和趋势分析等。考虑一下,如何通过 SQL 查询实现以下数据透视表?

产品   |渠道  |1|2|3|4|5|6|【合计】 
-------|-----|------|------|-------|------|------|------|-------
桔子   |京东  | 41289| 43913|  49803| 49256| 64889| 62649| 311799
桔子   |店面  | 41306| 37906|  48866| 48673| 58998| 58931| 294680
桔子   |淘宝  | 43488| 37598|  48621| 49919| 58530| 64626| 302782
桔子   |- -  |126083|119417| 147290|147848|182417| 186206| 909261
苹果   |京东  | 38269| 40593|  56552| 56662| 64493| 62045| 318614
苹果   |店面  | 43845| 40539|  44909| 55646| 56771| 64933| 306643
苹果   |淘宝  | 42969| 43289|  48769| 58052| 58872| 59844| 311795
苹果   |- -  |125083|124421| 150230|170360|180136| 186822| 937052
香蕉   |京东  | 36879| 36981|  51748| 54801| 64936| 60688| 306033
香蕉   |店面  | 41210| 39420|  50884| 52085| 60249| 67597| 311445
香蕉   |淘宝  | 42468| 41955|  52780| 54971| 56504| 59213| 307891
香蕉   |- -  |120557|118356| 155412|161857|181689| 187498| 925369
【总计】|- -  |371723|362194| 452932|480065|544242| 560526|2771682

我们同样可以利用分组汇总加上 CASE 表达式实现以上报表:

-- Oracle 和 PostgreSQL
SELECT CASE GROUPING(product) WHEN 1 THEN '【总计】' ELSE product END AS "产品",CASE GROUPING(channel) WHEN 1 THEN '--' ELSE channel END AS "渠道",SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 1 THEN amount END) "1 月",SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 2 THEN amount END) "2 月",SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 3 THEN amount END) "3 月",SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 4 THEN amount END) "4 月",SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 5 THEN amount END) "5 月",SUM(CASE EXTRACT(MONTH FROM saledate) WHEN 6 THEN amount END) "6 月",SUM(amount) "【合计】"
FROM sales_data
GROUP BY ROLLUP (product, channel)
ORDER BY product, channel;

其中,GROUP BY ROLLUP 子句表示统计不同产品不同渠道的销售金额小计、不同产品所有渠道的销售金额合计以及所有产品的销售总计,EXTRACT 函数加上 CASE 表达式用于获取每个月的销售金额。

对于 MySQL,我们需要使用 WITH ROLLUP 选项替换 ROLLUP。对于Microsoft SQL Server,我们需要使用 DATEPART 函数替换 EXTRACT 函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/779637.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day26 手撕各种集合底层源码(一)

Day26 手撕各种集合底层源码(一) 一、手撕ArrayList底层源码 1、概念: ArrayList的底层实现是基于数组的动态扩容结构。 2、思路: 1.研究继承关系 2.研究属性 3.理解创建集合的过程 – 构造方法的底层原理 4.研究添加元素的过程…

vue实现把Ox格式颜色值转换成rgb渐变颜色值(开箱即用)

图示: 核心代码: //将0x格式的颜色转换为Hex格式,并计算插值返回rgb颜色 Vue.prototype.$convertToHex function (colorCode1, colorCode2, amount) {// 确保输入是字符串,并检查是否以0x开头let newCode1 let newCode2 if (t…

关系型数据库mysql(5)存储引擎

目录 一.存储引擎的概念 二. MyISAM 和 InnoDB 2.1MyISAM介绍 2.2MyISAM支持的存储格式 2.2.1静态表(固定长度表) 2.2.2动态表 2.2.3压缩表 2.3场景举例 2.4.InnoDB 2.4.1场景举例 2.4.2企业选择存储引擎依据 三.查看存储引擎 3.1查看当前数…

IMU预积分【SLAM】

前言 预积分的推导过程比较多,所以这里只记录关键结论。 其实这些公式不太好记忆,因为预积分推导过程的想法来源很巧妙,无法看出物理意义。 预积分定义式(必须记住) 一切推导的来源: 最好记忆的旋转相对…

c语言教务成绩管理系统1000+

定制魏:QTWZPW,获取更多源码等 目录 题目 代码主函数 教务信息头文件 题目 编写一个C语言程序,实现一个教务成绩管理系统,至少能够管理30条学生信息。其中: 1)学生信息包括:基本信息和成绩信息。 2)基本信息包括:班级,学号,姓名,性别,专业,普通课程选修数…

C++中的STL简介与string类

目录 STL简介 STL的版本 STL的六大组件 string类 标准库中的string类 string类的常用接口 string类对象对容量的操作 size()函数与length()函数 capacity()函数 capacity的扩容方式 reserve()函数 resize()函数 string类对象的操作 push_back()函数 append()函数 operator()函数…

【01-20】计算机网络基础知识(非常详细)从零基础入门到精通,看完这一篇就够了

【01-20】计算机网络基础知识(非常详细)从零基础入门到精通,看完这一篇就够了 以下是本文参考的资料 欢迎大家查收原版 本版本仅作个人笔记使用1、OSI 的七层模型分别是?各自的功能是什么?2、说一下一次完整的HTTP请求…

1688中国站按关键字搜索工厂数据 API

公共参数 名称类型必须描述keyString是申请免费调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称(包括在请求地址中)[item_search,item_get,item_search_shop等]cacheString否[yes,no]默认y…

记录何凯明在MIT的第一堂课:神经网络发展史

https://www.youtube.com/watch?vZ5qJ9IxSuKo 目录 表征学习 主要特点: 方法和技术: LeNet 全连接层​ 主要特点: 主要特点: 网络结构: AlexNet 主要特点: 网络结构: Sigmoid Re…

经典永不过时 Wordpress模板主题

经得住时间考验的模板,才是经典模板,带得来客户的网站,才叫NB网站。 https://www.jianzhanpress.com/?p2484

最详细爬虫零基础教程12——某网评论爬取教程

文章目录 前言一、单页爬取二、翻页案例 前言 本文我们主要是讲述一个某网站评论爬取的案例 一、单页爬取 目标url:https://ke.qq.com/course/380991/12573838881968191?tuin7265bf35#term_id100454125 import jsonpath import requestsif __name__ __main__:#…

HCIP杂记

动态路由的评判标准 占用资源收敛速度选路 动态路由分类: IGP---内部网关协议 DV型---距离矢量型---RIPLS型---链路状态型---OSPFEGP---外部网关协议 OSPF---无类别的路由协议 组播224.0.0.5和224.0.0.6不存在周期更新机制,仅存在触发更新机制&#xff1…

Elasticsearch如何处理多个关键字查询

Elasticsearch (ES) 是一款强大的全文搜索和分析引擎。当针对Elasticsearch进行含有多个关键字的查询时,ES通常会使用其内置的查询DSL(Domain Specific Language)来处理这些请求。一般来讲,基于多个关键字,可以构建不同…

第十五届蓝桥杯第三期模拟赛第十题 ← 上楼梯

【问题描述】 小蓝要上一个楼梯,楼梯共有 n 级台阶(即小蓝总共要走 n 级)。小蓝每一步可以走 a 级、b 级或 c 级台阶。 请问小蓝总共有多少种方案能正好走到楼梯顶端?【输入格式】 输入的第一行包含一个整数 n 。 第二行包含三个整…

vulfocus环境搭建(kali搭建)

Vulfocus 是一个漏洞集成平台,将漏洞环境 docker 镜像,放入即可使用,开箱即用。 安装docker环境 个人不建议随意更换apt源,我换了几次遇到很多问题。 apt-get update apt-get upgrade(时间很久) apt-get i…

基于springboot的人事管理系统

人事管理系统 摘 要 人事管理系统理工作是一种繁琐的,务求准确迅速的信息检索工作。随着计算机信息技术的飞速发展,人类进入信息时代,社会的竞争越来越激烈,人事就越显示出其不可或缺性,成为学校一个非常重要的模块。…

小米汽车发布了

文章目录 1. 内容回顾2. 发布概要3. 畅想未来 1. 内容回顾 从小米宣布造车开始我就关注了,当时写过相关的文章来分析,这还是三年以前的事情,当时我是不看好小米造车的。 时光飞逝,在三月前,小米发布了它制造的第一台…

防止恶意软件和网络攻击的简单贴士

如今,缺少互联网的生活是难以想象的。然而,互联网的匿名性导致了网络攻击和恶意软件很猖獗。恶意软件会损坏我们的设备、窃取个人数据,并导致金钱损失。因此,保护计算机免受这些威胁显得至关重要。 一、确保操作系统和软件是最新版…

企业数据资产管理的战略价值与实施策略

一、引言 数据资产不仅记录了企业的历史运营情况,更能够揭示市场的未来趋势,为企业的决策提供有力支持。因此,如何有效地管理和利用数据资产,已经成为企业竞争力的重要体现。本文将探讨企业数据资产管理的战略价值与实施策略&…