Oracle 聚合实现小计、合计 (GROUP BY ROLLUP)

本文介绍了如何使用SQL的Rollup字句创建统计报表,通过示例展示了如何对销售数据按季度和月份进行小计和合计。Rollup作为GroupBy的扩展,能自动生成多级汇总数据。同时,文章提到了GROUPING()、GROUP_ID()和GROUPING_ID()辅助函数在统计报表中的作用,并探讨了Pivot函数在行列转换中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.先创建一个测试表

-- Create table 水果月销售记录表
create table C_FRUITS_SALES_RECORD_T
(
  quarter VARCHAR2(20),--季度
  month   VARCHAR2(20),--月份
  apple   NUMBER,--苹果销量
  banana  NUMBER,--香蕉销量
  orange  NUMBER--橘子销量
)

导入测试数据

   QUARTERMONTHAPPLEBANANAORANGE
1第一季度1509080
2第一季度2659460
3第一季度38011055
4第二季度412011550
5第二季度57512045
6第二季度66512550
7第三季度78011550
8第三季度88013060
9第三季度99511080
10第四季度1012090120
11第四季度1113585160
12第四季度128080120

现在我们对销售数据出一张统计报表,要求对每季度数据进行小计,所有数据进行合计应该怎么做呢?

我们可能想到使用要用union对明细数据和统计数据进行合并输出,或者在前端进行遍历后生成统计数据

2.使用ROLLUP字句

现在我们有更好的选择,使用RollUp

RollUp是Group By函数的字句,用于对分组数据产生统计数据

针对上述需求我们可以用一下SQL实现

SELECT NVL(T.QUARTER, '合计') AS QUARTER,
       NVL(T.MONTH, '小计') AS MONTH,
       SUM(T.APPLE) AS APPLE,
       SUM(T.BANANA) AS BANANA,
       SUM(T.ORANGE) AS ORANGE
  FROM C_FRUITS_SALES_RECORD_T T
 GROUP BY ROLLUP(T.QUARTER, T.MONTH)
 ORDER BY T.QUARTER, T.MONTH

查询结果如下:

   QUARTERMONTHAPPLEBANANAORANGE
1第一季度1509080
2第一季度2659460
3第一季度38011055
4第一季度小计195294195
5第三季度78011550
6第三季度88013060
7第三季度99511080
8第三季度小计255355190
9第二季度412011550
10第二季度57512045
11第二季度66512550
12第二季度小计260360145
13第四季度1012090120
14第四季度1113585160
15第四季度128080120
16第四季度小计335255400
17合计小计10451264930

那假如我们只需要合计,不要小计呢?也很简单,使用下边的代码

SELECT NVL(T.QUARTER, '合计') AS QUARTER,
       NVL(T.MONTH, '小计') AS MONTH,
       SUM(T.APPLE) AS APPLE,
       SUM(T.BANANA) AS BANANA,
       SUM(T.ORANGE) AS ORANGE
  FROM C_FRUITS_SALES_RECORD_T T
 GROUP BY ROLLUP((T.QUARTER, T.MONTH))
 ORDER BY T.QUARTER, T.MONTH

大家有注意到区别在哪了吗?

第一个是:GROUP BY ROLLUP(T.QUARTER, T.MONTH)

第二个是:GROUP BY ROLLUP((T.QUARTER, T.MONTH))

我们可以理解为 ROLLUP 括号 中的每个栏位都是一个维度,ROLLUP会按照顺序为 维度生成统计数据,添加在结果集中,而二级括号可以把几个栏位看做一个整体当做一个维度。

如:ROLLUP(A,B,C,D)会在结果集中添加(A,B,C,D)、 (A,B,C)、(A,B)、(A)、(null) 五种 统计数据

    而ROLLUP((A,B),C,D)会在结果集中添加 (A,B,C,D)、(A,B,C)、(A,B)、(null) 四种 统计数据

你也可以使用  GROUP BY  C, D ,ROLLUP((A, B)) 等方法去实现具体需求。

如果觉得有些乱,可以用一下代码,调整  GROUP BY 和 ROLLUP中的栏位看看输出结果

SELECT A, B, C, D, SUM(N)
  FROM (SELECT 1 AS A, 2 AS B, 3 AS C, 4 AS D, 5 AS N FROM DUAL)
 GROUP BY ROLLUP(A, B, C, D)

3.辅助函数

(1)GROUPING()函数:传入一列,用于判断是否为统计行,如上边示例的NVL(T.QUARTER, '合计') AS QUARTER,NVL(T.MONTH, '小计') AS MONTH 可以写作DECODE(GROUPING(T.QUARTER), 1, '合计', T.QUARTER) AS QUARTER,DECODE(GROUPING(T.MONTH), 1, '小计', T.MONTH) AS MONTH

(2)GROUP_ID()函数:无参数,相同分组出现的次数,可以用于过滤重复数据

(3)GROUPING_ID()函数:多列参数,对多列依次使用GROUPING()并对多列结果进行拼接成二进制数值,再转十进制输出结果,如上边 GROUPING_ID(T.QUARTER, T.MONTH) 小计行返回1,合计行返回3

4.相关函数

(1)PIVOT:行转列函数,假如你表格中每种水果不是单独存储,是用一列 种类 的栏位来标示时,你可能需要用到PIVOT函数,具体使用方法可以搜索一下,后边有时间我会详细写一下

### 使用 `GROUP BY` 进行数据聚合Oracle 数据库中,`GROUP BY` 子句用于将具有相同值的行组合在一起。通常与聚合函数一起使用来执行汇总操作,如计算总数、平均值等。 #### 聚合函数的应用 常见的聚合函数包括但不限于: - **AVG()**: 计算平均值[^4]。 - **SUM()**: 对数值列求和。 - **COUNT()**: 统计记录数量。 - **MAX()**: 获取最大值。 - **MIN()**: 获取最小值。 这些函数可以应用于特定列以获取所需的结果集。 #### 正确编写带有 `GROUP BY` 的查询语句 为了防止出现“不是 GROUP BY 表达式”的错误,在构建 SQL 查询时需注意以下几点: - 所有的非聚合函数字段应当出现在 `SELECT` 列表以及 `GROUP BY` 子句之中[^1]。 - 避免直接在 `GROUP BY` 中使用别名,而应该重复原始列名称或表达式。 例如,考虑如下表格结构及其上的查询: | Name | Department_ID | |-- 错误示范:试图通过别名分组会引发异常 SELECT department_id AS dep, COUNT(*) FROM employees GROUP BY dep; -- 正确做法:应按照实际列名而非别名来进行分组 SELECT department_id, COUNT(*) FROM employees GROUP BY department_id; ``` #### 结合 `HAVING` 来过滤分组结果 当需要基于某些条件进一步筛选已分组的数据时,则需要用到 `HAVING` 子句而不是 `WHERE`。因为后者无法识别由 `GROUP BY` 创建的新逻辑单元。 ```sql -- 示例:找出至少有两个员工以上的部门编号及人数 SELECT department_id, COUNT(*) FROM employees GROUP BY department_id HAVING COUNT(*) > 1; ``` 此外,还可以利用更复杂的 `ROLLUP`, `CUBE` 或者 `GROUPING SETS` 关键字实现多级分类汇总功能[^3]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值