Oracle 中總計和小計使用的函數



@[TOC](總計和小計、逐行累計求和)
### 一、總計和小計使用函數
#### 1、rollup
group by 我們都知道,是一個分組函數,用於針對某一列做分組操作。
但是當它搭配其他的函數一起使用的時候,就像一對男女孩,撞出不一樣的火花。
==rollup(字段1,字段2,.....)
rollup和group by一起使用,可以針對每一個分組返回一個小計行,以及為所有的分組返回一個總計行(一個字段就是返回總計行,多個字段就是返回每一個分組的一個小計行和一個總計行)==
實踐是檢驗真理的唯一標准,那我們來實踐一下,我們先來快速創建一個表。有多快,很快很快的那種。

```handlebars
CREATE TABLE EMP (
"EMPNO" NUMBER(4) NOT NULL ,
"ENAME" VARCHAR2(10 BYTE) ,
"JOB" VARCHAR2(9 BYTE) ,
"SAL" NUMBER(7,2) ,
"DEPTNO" NUMBER(2)
)
INSERT INTO "SCOTT"."EMP" VALUES ('1', '張三', '開發', '10000', '10');
INSERT INTO "SCOTT"."EMP" VALUES ('2', '李四', '運維', '6000', '20');
INSERT INTO "SCOTT"."EMP" VALUES ('3', '王五', '測試', '6000', '30');
INSERT INTO "SCOTT"."EMP" VALUES ('4', '麻子', '開發', '12000', '10');
```
==當我們的rollup里面只有一個字段的時候,就返回一個總計行==

```handlebars
select deptno,sum(sal) from emp
group by rollup(deptno);
查詢結果:
10 22000
20 6000
30 6000
34000
```
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200523100648667.png)
==當我們傳遞兩個列字段的時候,就會按照第一個字段進行分組,返回一個小計行,最后返回一個總計行==

```handlebars
select ENAME,DEPTNO,sum(sal) from emp group by rollup(ENAME,DEPTNO);
李四 20 6000
李四 6000
麻子 10 12000
麻子 12000
王五 30 6000
王五 6000
張三 10 10000
張三 10000
34000

select ENAME,DEPTNO,sum(sal) from emp group by rollup(DEPTNO,ENAME);
麻子 10 12000
張三 10 10000
10 22000
李四 20 6000
20 6000
王五 30 6000
30 6000
34000
```
根據rollup()傳入的第一個字段不同,返回的結果是不一樣的。我的理解是,rollup()傳遞多字段的時候,會==先對多字段進行分組,然后對第一個字段進行分組==,比如上面的ename是第一個字段,多字段分組后就有四種,然后對第一字段分組后還剩四種,並且返回一個小計行,最后返回一個總計行
![在這里插入圖片描述](https://img-blog.csdnimg.cn/2020052310123379.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dYQjUyMTEyMTgxMzE0,size_16,color_FFFFFF,t_70)
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200523101249222.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dYQjUyMTEyMTgxMzE0,size_16,color_FFFFFF,t_70)
#### 2、cube
cube()傳遞一個字段的時候,和rollup是一樣的結果

```handlebars
select DEPTNO,sum(sal) from emp group by cube(DEPTNO) order by deptno;
10 22000
20 6000
30 6000
34000
```
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200523103405378.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dYQjUyMTEyMTgxMzE0,size_16,color_FFFFFF,t_70)
但是cube()傳遞多個字段的時候,就和rollup()不一樣了,cube()對多字段的處理是先對所有的多字段進行分組,然后==對第一個字段進行分組,再對第二個字段進行分組,意思就是兩種分組合起來了==,從下面的結果我們就可以看出來,比如第二個字段是deptno,分組后會把相同的10做為一組,所以可以看到根據ename分組會產生一個小計行,再根據deptno分組后產生了一個小計行,最后返回一個總計行。就等於在rollup()的基礎上,我們多了幾行分組的結果

```handlebars
select ENAME,DEPTNO,sum(sal) from emp group by cube(ENAME,DEPTNO);
34000
10 22000
20 6000
30 6000
李四 6000
李四 20 6000
麻子 12000
麻子 10 12000
王五 6000
王五 30 6000
張三 10000
張三 10 10000

select ENAME,DEPTNO,sum(sal) from emp group by cube(DEPTNO,ENAME);
34000
李四 6000
麻子 12000
王五 6000
張三 10000
10 22000
麻子 10 12000
張三 10 10000
20 6000
李四 20 6000
30 6000
王五 30 6000
```

![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200523103747346.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dYQjUyMTEyMTgxMzE0,size_16,color_FFFFFF,t_70)
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200523104220398.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dYQjUyMTEyMTgxMzE0,size_16,color_FFFFFF,t_70)
#### 3、grouping
GROUPING函數可以接受一列,返回0或者1。==如果列值為空,那么GROUPING()返回1;如果列值非空,那么返回0==。GROUPING只能在使用ROLLUP或CUBE的查詢中使用。我的理解就是==用來填充使用rollup()和cube()產生的null值==

```handlebars
select grouping(deptno),DEPTNO,sum(sal) from emp group by rollup(DEPTNO) ;
0 10 22000
0 20 6000
0 30 6000
1 34000
```
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200523105005605.png)
我們使用==decode函數或case when==來填充為null的值。
==DECODE(value,if 條件1,then 值1,if 條件2,then 值2,...,else 其他值)==

```handlebars
select decode(grouping(deptno),1,'總計',DEPTNO) deptno,sum(sal) from emp group by rollup(DEPTNO) ;
10 22000
20 6000
30 6000
總計 34000
```
!![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200523105431244.png)
可以看到我們把第一次查詢結果中的null填充了一個“總計”,這里使用的是rollup()配合,使用cube()也是一樣的。
#### 4、grouping sets
grouping sets()傳遞多字段就是分別對字段進行分組了,產生的結果就是多個字段分別分組后合起來的行。

```handlebars
select ENAME,DEPTNO,sum(sal) from emp group by grouping sets(ENAME,DEPTNO);
王五 6000
李四 6000
張三 10000
麻子 12000
30 6000
20 6000
10 22000
```
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200523110031412.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dYQjUyMTEyMTgxMzE0,size_16,color_FFFFFF,t_70)
從結果我們可以看出,分別針對ename分組產生四行結果和對deptno分組產生三行結果。
#### 5、grouping_id
grouping_id()配合grouping()函數使用,會根據grouping()的值來決定,比如==grouping(字段1)為0,grouping(字段2)為1,則grouping_id(字段1,字段2)的結果就是1,如果grouping(字段1)為1,grouping(字段2)為0,則grouping_id(字段1,字段2)的結果就是2,如果grouping(字段1)為1,grouping(字段2)為1,則grouping_id(字段1,字段2)的結果就是3,==

```handlebars
select ename,deptno,sum(sal),
grouping(ename),
grouping(deptno),
grouping_id(ename,deptno)
from emp group by rollup(ename,deptno) ;

李四 20 6000 0 0 0
李四 6000 0 1 1
麻子 10 12000 0 0 0
麻子 12000 0 1 1
王五 30 6000 0 0 0
王五 6000 0 1 1
張三 10 10000 0 0 0
張三 10000 0 1 1
34000 1 1 3
```
![在這里插入圖片描述](https://img-blog.csdnimg.cn/20200523111437863.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1dYQjUyMTEyMTgxMzE0,size_16,color_FFFFFF,t_70)
### 二、逐行累計求和方法(OVER函數)
#### 1、sum(字段) over(partition by 字段1 order by 字段2....)
==over(partition by 字段1 order by 字段2....)
按字段1指定的字段進行分組排序,或者說按字段字段2的值進行分組排序==

```handlebars
select deptno,sal,
sum(sal) over (partition by deptno order by deptno) 逐行累計求和
from emp;
10 10000 22000
10 12000 22000
20 6000 6000
30 6000 6000

select deptno,sal,
sum(sal) over ( order by deptno) 逐行累計求和
from emp
10 10000 22000
10 12000 22000
20 6000 28000
30 6000 34000
```
從上面的結果我們可以看出,加了==partition by deptno==就會根據指定字段分組逐行累加求和,否則全部逐行累加求和。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM