1.組及組函數回顧
SELECT [column,]group_function(column)...
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[ORDER BY column];
例1:計算工作崗位以CL開頭的各部門僱員的平均薪水、有佣金收入的僱員數和最晚受僱日期
SELECT AVG(sal),COUNT(comm),MAX(hiredate)
FROM emp
WHERE job LIKE 'CL%';
例2:查詢emp表,按照部門編號和工作崗位分組,顯示部門編號、工作崗位、薪水合計、有佣金收入的僱員數
SELECT deptno,job,SUM(sal),COUNT(comm)
FROM emp
GROUP BY deptno,job;
2.HAVING子句的回顧
SELECT [column,]group_function(column)...
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[HAVING having_expression]
[ORDER BY column] ;
例:查詢emp表,按照部門編號進行分組,顯示平均薪水高於$2000的部門編號和平均薪水
SELECT deptno,AVG(sal)
FROM emp
GROUP BY deptno
HAVING AVG(sal)>2000;
3.ROLLUP操作
SELECT [column,]group_function(column)...
FROM table
[WHERE condition]
[GROUP BY [ROLLUP]group_by_expression]
[HAVING having_expression]
[ORDER BY column] ;
1)ROLLUP分組產生一個包含常規分組行和小計值的結果集
2)ROLLUP是一個GROUP BY 子句的擴展
3)用ROLLUP操作產生小計和累計
例:
SELECT deptno department_id,job job_id,SUM(sal) salary
FROM emp
WHERE deptno<60
GROUP BY ROLLUP(deptno,job);
結果:
DEPARTMENT_ID JOB_ID SALARY
10 3000
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
10 11750 //dept10薪水小計
20 CLERK 3100
20 ANALYST 6000
20 MANAGER 2975
20 12075 //dept20薪水小計
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
30 9400 //dept30薪水小計
33225 //所有salary之和
4.CUBE操作
SELECT [column,]group_function(column)...
FROM table
[WHERE condition]
[GROUP BY [CUBE]group_by_expression]
[HAVING having_expression]
[ORDER BY column] ;
1)CUBE是GROUP BY子句的擴展
2)CUBE分組是產生一個包含ROLLUP行和交叉錶行的結果集
例:
SELECT deptno department_id,job job_id,SUM(sal) salary
FROM emp
WHERE deptno<60
GROUP BY CUBE(deptno,job)
ORDER BY 1;
結果:
DEPARTMENT_ID JOB_ID SALARY
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
10 3000
10 11750
20 ANALYST 6000
20 CLERK 3100
20 MANAGER 2975
20 12075
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
30 9400
ANALYST 6000
CLERK 5350
MANAGER 8275
PRESIDENT 5000
SALESMAN 5600
3000
33225
5.GROUPING函數
SELECT [column,]group_function(column),GROUPING(expr)
FROM table
[WHERE condition]
[GROUP BY [ROLLUP][CUBE]group_by_expression]
[HAVING having_expression]
[ORDER BY column] ;
1)GROUPING函數既可以用於CUBE操作,也可以用於ROLLUP操作
2)用GROUPING函數模擬能夠發現在一行中的構成小計的分組
3)GROUPING函數返回0或1
例:
SELECT deptno deptid,job,SUM(sal),
GROUPING(deptno) GRP_DEPT,
GROUPING(job) GRP_JOB
FROM emp
WHERE deptno<50
GROUP BY ROLLUP(deptno,job);
結果:
DEPTID JOB SUM(SAL) GRP_DEPT GRP_JOB
10 3000 0 0
10 CLERK 1300 0 0
10 MANAGER 2450 0 0
10 PRESIDENT 5000 0 0
10 11750 0 1
20 CLERK 3100 0 0
20 ANALYST 6000 0 0
20 MANAGER 2975 0 0
20 12075 0 1
30 CLERK 950 0 0
30 MANAGER 2850 0 0
30 SALESMAN 5600 0 0
30 9400 0 1
33225 1 1
已選擇14行。
6.分組集
1)GROUPING SETS是GROUP BY子句更進一步的擴展
2)能夠用GROUPING SETS在同一查詢中定義多個分組
3)Oracle服務器計算在GROUPING SETS子句中指定的所有分組
4)分組集合的效率:
-對基表僅進行一次查詢
-不需要寫複雜的UNION語句
-GROUPING SETS有更多的元素,更好的執行性能
例:
SELECT deptno department_id,job job_id,
mgr manager_id,AVG(sal) salary
FROM emp
GROUP BY GROUPING SETS((deptno,job),(job,mgr));
結果:
DEPARTMENT_ID JOB_ID MANAGER_ID SALARY
10 3000
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
20 CLERK 1550
20 ANALYST 3000
20 MANAGER 2975
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 1400
3000
CLERK 7698 950
CLERK 7782 1300
CLERK 7788 1100
CLERK 7902 2000
ANALYST 7566 3000
MANAGER 7839 2758.33333
SALESMAN 7698 1400
PRESIDENT 5000
已選擇19行。
7.複合列
1)複合列是一個作爲整體被處理的列集合
-ROLLUP(a,(b,c),d)
2)爲了指定複合列,用GROUP BY子句來分組在圓括號內的列,因此Oracle服務器在進行ROLLUP
或CUBE操作時將它們作爲一個整體來處理
3)當使用ROLLUP或CUBE時,複合列將跳過在確定級別上的聚合
例:
SELECT deptno,job,mgr,SUM(sal)
FROM emp
GROUP BY ROLLUP(deptno,(job,mgr));
結果:
DEPTNO JOB MGR SUM(SAL)
10 3000
10 CLERK 7782 1300
10 MANAGER 7839 2450
10 PRESIDENT 5000
10 11750
20 CLERK 7788 1100
20 CLERK 7902 2000
20 ANALYST 7566 6000
20 MANAGER 7839 2975
20 12075
30 CLERK 7698 950
30 MANAGER 7839 2850
30 SALESMAN 7698 5600
30 9400
33225
練習
1.查詢emp表,根據部門編號、工作崗位、所屬的經理編號進行分組,使用ROLLUP查詢薪水的合計
SELECT deptno,job,mgr,SUM(sal)
FROM emp
GROUP BY ROLLUP(deptno,job,mgr);
2.查詢emp表,根據部門編號、工作崗位、所屬的經理編號進行分組,使用CUBE查詢薪水的合計
SELECT deptno,job,mgr,SUM(sal)
FROM emp
GROUP BY CUBE(deptno,job,mgr);
3.用GROUPING SETS寫一個查詢,顯示下面的分組:
deptno,mgr,job
deptno,job
mgr,job
查詢計算每個分組的工資總數
SELECT deptno,job,mgr,SUM(sal)
FROM emp
GROUP BY GROUPING SETS((deptno,job,mgr),(deptno,job),(mgr,job));