[toc]sql
提到 Group by 子句,你須要先理解一個東西:函數的分類。提到函數分類,你腦海裏面須要瞬間想到Oracle中的函數分類:單行函數(Single-row functions)、多行函數(Multiple-row functions)。請把中文英文都背下來,也就這麼兩個,這是Oracle的函數分類的體系,很重要。之後再遇到這個知識點,你至少可以成竹在胸,張口就來。函數
舉個現炒板栗:你說你要查 EMP 表中,全部人員的名字和他對應的工資,因而發出下面的語句並獲得結果。spa
SQL> select ename,sal from emp; ENAME SAL -------------------- ---------- SMITH 800 ALLEN 1600 WARD 1250 JONES 2975 MARTIN 1250 BLAKE 2850 CLARK 2450 SCOTT 3000 KING 5000 TURNER 1500 ADAMS 1100 JAMES 950 FORD 3000 MILLER 1300 14 rows selected.
你會發現,14行結果中,每一個人的名字都是大寫(注意:Oracle 語句不區分大小寫,可是存的值是區分大小寫的,SCOTT 和 scott 是兩個值)。你說你看的不習慣,問可否把名字處理成「小寫」字母來顯示?code
這裏咱們給出一個東西 lower(),它是什麼?你先無論,先叫它「函數」,咱們用它把名字處理一下:發出如下命令並獲得結果。ip
SQL> select lower(ename),sal from emp; LOWER(ENAME) SAL -------------------- ---------- smith 800 allen 1600 ward 1250 jones 2975 martin 1250 blake 2850 clark 2450 scott 3000 king 5000 turner 1500 adams 1100 james 950 ford 3000 miller 1300 14 rows selected.
你會發現,名字經過 lower 函數處理以後,所有變爲了小寫,更重要的是,處理完畢後,結果集的行數(14行)和處理前結果集的行數(14行)徹底一致,也就是說,用了這個 lower 函數處理數值,最終的結果條目數是一比一的呈現,因而,咱們稱 lower 這個函數爲:單行函數(針對結果集的每一行都返回一個值)。it
你說你要查 EMP 表中,全部人員工資的總和,因而發出下面的語句並獲得結果。io
SQL> select sum(sal) from emp; SUM(SAL) ---------- 29025
這個 sum 是什麼,也是個函數,你會發現,使用了這個 sum 求和函數後,最終返回一行數據。原來 14 行,使用了 sum 變爲 1 行,因而,咱們稱 sum 這個函數爲:多行函數(針對<font color=#FF0000>每一個結果集</font>只返回一個值)。<font color=#FF0000>不要這麼記</font>:針對多行只返回一個值的稱做多行函數。function
再看個例子:按照部門,查詢每一個部門的工資總和,因而發出下面的語句並獲得結果。class
SQL> select deptno,sum(sal) from emp group by deptno order by 1; DEPTNO SUM(SAL) ---------- ---------- 10 8750 20 10875 30 9400
呈現的結果爲<font color=#FF0000>3行</font>數據,處理前一共 14 行,經過 sum 求和函數處理後獲得 3 行數據,請問:sum 是多行函數嗎?固然是!這裏涉及到一個基本概念的理解,若是你認爲:~~<font color=#FF0000>針對多行返回一行稱爲多行函數。</font>~~那麼我經過這個例子就能夠反駁你,由於我針對多行(14行)返回了 3 行,不是 1 行。你能告訴我說 sum 不是多行函數嗎?因此,這種說法自己就存在歧義。date
而官方教材對多行函數的精準描述是這樣的:<font color=#FF0000>Return one result per set of rows.</font>什麼意思?針對每一個行集(或理解爲結果集)返回一個值(就是一行)。這麼記,你對多行函數的概念就不會迷迷糊糊了。
那如何理解<font color=#FF0000>行集(結果集)</font>這個概念?咱們求全部部門的工資總和 sum(sal) ,這個行集就是 14 行數據,最終返回 1 行,就是總額。咱們按照部門,求每一個部門的工資總和,所以要按照部門分開,求出每一個部門的工資總和,咱們先看下 10 號部門的行數:
SQL> select count(1) from emp where deptno=10; COUNT(1) ---------- 3
10 號部門有 3 行數據,所以,對於 10 號部門工資求和的行集就是 3 行,經過計算這 3 行的數據,最終返回 1 行,就是 10 號部門的工資總額。
再來看 20 號部門:這個部門一共 5 行數據,所以,對於 20 號部門來講,行集就是 5 行,最終返回 1 行,就是 20 號部門的工資總額。
SQL> select count(1) from emp where deptno=20; COUNT(1) ---------- 5
30 號部門也同樣:一共 6 行數據,所以,對於 30 號部門來講,行集就是 6 行,最終返回 1 行,就是 30 號部門的工資總額。
SQL> select count(1) from emp where deptno=30; COUNT(1) ---------- 6
例如:查詢全部部門工資總和
SQL> select sum(sal) from emp;
例如:按照部門分組查詢每一個部門的工資總和
SQL> select deptno,sum(sal) from emp group by deptno;
注意:select 子句中包含兩個字段 deptno 和 sum(sal) ,由於 sal 字段使用了多行函數,因此在後面 group by 子句中只須要包含 deptno 便可。
# 如下語句都是正確的。從業務邏輯層面來講,毫無心義,只是爲了展現語句規則。 SQL> select sum(sal) from emp group by ename; SQL> select sum(sal) from emp group by ename,empno; SQL> select sum(sal) from emp group by ename,empno,sal;
注意下嵌套函數:嵌套函數不是一個函數,而是對函數疊加使用的描述。例如:求出哪一個部門工資總和最大。
SQL> select max(sum(sal)) from emp group by deptno; MAX(SUM(SAL)) ------------- 10875
這個 max(sum(sal)) 就是一個嵌套函數,多行函數嵌套最多嵌套 2 層。單行函數嵌套無限制。
例如:下面語句報錯
SQL> select deptno,max(sum(sal)) from emp group by deptno; select deptno,max(sum(sal)) from emp group by deptno * ERROR at line 1: ORA-00937: not a single-group group function
Which query is valid? A. SELECT dept_id,join_date,sum(salary) FROM employees GROUP BY dept_id,join_date; B. SELECT dept_id,join_date,sum(salary) FROM employees GROUP BY dept_id; C. SELECT dept_id,MAX(AVG(salary)) FROM employees GROUP BY dept_id; D. SELECT dept_id,AVG(MAX(salary)) FROM employees GROUP BY dept_id;
答案:<font color=#F8F8FF>A</font>