八、分組查詢(group by)

一、概要

Group By語句從英文的字面意義上理解就是“根據(by)一定的規則進行分組(Group)”。它的作用是通過一定的規則將一個數據集劃分成若干個小的區域,然後針對若干個小區域進行數據處理。 如果在查詢的過程中需要按某一列的值進行分組,以統計該組內數據的信息時,就要使用group by子句。不管select是否使用了where子句都可以使用group by子句。
group by子句一定要與聚合函數結合使用,否則沒有意義。

二、語法格式

SELECT [DISTINCT] * | 列名稱 [別名] ,... | 聚合函數   
FROM 表名                               
[WHERE 條件]                                                 
[GROUP BY 分組字段, 分組字段, ...]                                   
[WITH ROLLUP]]
[HAVING where_contition]
[ORDER BY 字段 [ASC | DESC] , 字段 [ASC | DESC] ,...]              

參數進行以下說明:

  • 聚合函數, sum(求和)、 count(*)(記錄數)、 max(最大值)、 min(最小值)、avg(平均值)。
  • GROUP BY 關鍵字表示要進行分類聚合的字段。
  • WITH ROLLUP 是可選語法, 表明是否對分類聚合後的結果進行再彙總。
  • HAVING 關鍵字表示對分類後的結果再進行條件的過濾。

注意: having 和 where 的區別在於having 是對聚合後的結果進行條件的過濾, 而 where 是在聚合前就對記錄進行過濾, 如果邏輯允許, 我們儘可能用 where 先過濾記錄, 這樣因爲結果集減小, 將對聚合的效率大大提高, 最後再根據邏輯看是否用 having 進行再過濾。

三、數據

創建一個名稱爲 emp 的表。 表中包括 3 個字段, ename(姓名), hiredate(僱用日期)、sal(薪水), deptno (部門):

mysql> create table emp(ename varchar(10),hiredate date,sal decimal(10,2),deptno int(2));
Query OK, 0 rows affected (0.02 sec)

插入數據:

+--------+------------+---------+--------+
| ename | hiredate | sal | deptno |
+--------+------------+---------+--------+
| bjguan | 2004-04-02 | 5000.00 | 1 |
| zzx | 2000-01-01 | 2000.00 | 1 |
| lisa | 2003-02-01 | 4000.00 | 2 |
| bzshen | 2005-04-01 | 4000.00 | 3 |
+--------+------------+---------+--------+

四、示例代碼

查詢公司總人數

mysql> select count(*) from emp;
+----------+
| count(*) |
+----------+
| 4 |
+----------+
1 row in set (0.00 sec)

統計各個部門的人數:

mysql> select deptno,count(*) from emp group by deptno;
+--------+----------+
| deptno | count(*) |
+--------+----------+
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
+--------+----------+
3 rows in set (0.00 sec)

顯示每個部門員工的平均工資

mysql> SELECT deptno ,AVG(sal) 平均工資
> FROM emp GROUP BY deptno;
+--------+----------+
| deptno | 平均工資 |
+--------+----------+
| 1 | 3500.00 |
| 2 | 4000.00 |
| 3 |4000.00 |
+--------+----------+
3 rows in set (0.00 sec)

五、注意事項

(1):

GROUP BY後不可以接列的別名(根據執行順序分析就知道了)
SELECT  deptno dn ,AVG(sal)
FROM emp
GROUP BY dn;  --錯誤

(2):

GROUP BY 後不能接數字
SELECT  deptno dn ,AVG(sal)
FROM emp
GROUP BY 1;   --錯誤

(3):

GROUP BY 後不可以接select後沒有的列名
SELECT  deptno dn ,AVG(sal)
FROM emp
GROUP BY job; --錯誤

(4):
如果一個SELECT中使用了聚合函數,任何不在聚合函數中的列(表達式)必須要在GROUP BY中

SELECT  job ,deptno dn ,AVG(sal) 
FROM emp
GROUP BY job;   --deptno列group by 後面沒有,使用會報錯

(3)和(4)總結爲一句話:

1、在select中出現的列名必須在group by 中出現,否則,其他列名只能在聚合函數中使用;而在group by 中出現的字段不一定要在select中出現

group by之前可以使用where過濾數據,因爲where是在分組之前起作用的

六、使用HAVING過濾分組

1、作用:在分組之後再過濾掉不符合條件的分組
2、與where的區別
相同作用——都是根據條件過濾數據;
不同的是where是在分組之前過濾數據,having是分組之後過濾分組數據。
原則:能在where裏過濾的數據就不要在having裏面去過濾
3、示例代碼
統計人數大於 1 人的部門:

mysql> select deptno,count(*) from emp group by deptno having count(*)>1;
+--------+----------+
| deptno | count(*) |
+--------+----------+
| 1 | 2 |
+--------+----------+
1 row in set (0.00 sec)

七、分類聚合後再彙總WITH ROLLUP

既要統計各部門人數, 又要統計總人數:

mysql> select deptno,count(1) from emp group by deptno with rollup;
+--------+----------+
| deptno | count(1) |
+--------+----------+
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
| NULL | 4 |    ————彙總
+--------+----------+
4 rows in set (0.00 sec)

我們可以使用 coalesce 來設置一個可以取代 NUll 的名稱
coalesce 語法:
COALESCE(value,…)是一個可變參函數,可以使用多個參數。
作用:接受多個參數,返回第一個不爲NULL的參數,如果所有參數都爲NULL,此函數返回NULL;當它使用2個參數時,和IFNULL函數作用相同。

select coalesce(null,2,3); // Return 2

select coalesce(null,null,3); // Return 3

select coalesce(1,2,3); // Return 1

以下實例中如果deptno 爲空,我們使用總數代替:

mysql> select coalesce(deptno ,“總數”),count(1) from emp group by deptno with rollup;
+--------+----------+
| deptno | count(1) |
+--------+----------+
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
| 總數| 4 |   
+--------+----------+
4 rows in set (0.00 sec)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章