咱們常常須要彙總數據而不用把它們實際檢索處出來,爲此MySQL提供了專門的函數。使用這些函數,MySQL查詢可用於檢索數據,以便分析和報表的生成。這種類型的檢索例子有如下幾種:express
上述的例子都須要對錶中數據(而不是實際數據自己)彙總。所以,返回實際表數據是對時間和處理資源的一種浪費(更不用說帶寬了)。函數
MySQL提供了5個彙集函數。學習
彙集函數(aggregate function)運行在行組上,計算和返回單個值的函數。設計
函數 | 說明 |
---|---|
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行數 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值之和 |
下面簡單介紹這些函數code
先建立下面的表:排序
CREATE TABLE student( sid INT PRIMARY KEY, sname VARCHAR(20), ssex CAHR(1) ); CREATE TABLE score( sid INT PRIMARY KEY, sname VARCHAR(20), smath INT, senglish INT );
AVG()經過對錶中行數計數並計算特定列值之和,求得該列的平均值。AVG()可用來返回全部列的平均值,也能夠用來返回特定列平均值。資源
AVG()只能用來肯定特定數值列的平均值,並且列名必須做爲函數參數給出。爲了得到多個列的平均值,必須使用多個AVG()函數。
AVG()函數忽略列值爲NULL的行。數學
來使用AVG()函數來查詢成績表score中數學成績的平均分(本身隨便加上幾個數):io
SELECT AVG(smath) AS avg_smath FROM score;
AVG()也可用用來肯定特定列平均值,配合WHERE子句。table
COUNT()函數肯定表中行的數目或符合特定條件的行的數目。
COUNT()函數有兩種使用的方式:
好比:返回學生總數:
SELECT COUNT(*) FROM student;
返回女生總數(特定列):
SELECT COUNT(ssex) FROM student WHERE ssex='女';
若是指定列名,則指定列的值爲空的行被COUNT()函數忽略,但若是COUNT()函數中用的是星號(*),則不忽略。
MAX() 返回指定列中的最大值。MAX() 要求指定列名。
好比:返回成績表中數學成績的最高分:
SELECT MAX(smath) FROM score;
雖然MAX()通常用來找出最大的數值或日期值,但MySQL容許將它用來返回任意列中的最大值,包括返回文本列中的最大值。在用於文本數據時,若是數據按相應的列排序,則MAX()返回最後一行。MIN()函數也是,可是相反,返回最前面的行。
MAX()、MIN()都是忽略列值爲NULL的行。
MIN() 返回指定列中的最小值。MIN() 要求指定列名。
好比:返回成績表中數學成績的最低分:
SELECT MIN(smath) FROM score;
SUM()用來返回指定列值的和(總計)。
好比返回一個班中的數學成績的總分:
SELECT SUM(smath) FROM score;
利用標準的算術操做符,全部的彙集函數均可以用來執行多個列上的計算。
SUM()函數忽略列值爲NULL的行。
以上5個彙集函數均可以以下使用:
下面舉例指定DISTINCT參數的用法:好比成績表中數學成績的平均分,平均分只考慮各個不一樣的分數:
SELECT AVG(DISTINCT smath) AS avg_smath FROM score;
若是指定列名,則DISTINCT只能用於COUNT(),DISTINCT不能用於COUNT(*),所以不容許使用COUNT(DISTINCT),不然會產生錯誤。相似地,DISTINCT必須使用列名,不能用於計算或表達式。
DISTINCT可用於MAX()和MIN(),可是沒有意義。
實際上SELECT語句可根據須要包含多個彙集函數。
使用匯集函數,最好使用別名。
小結:彙集函數用來彙總數據,這些函數都是高效設計,它們返回的結果通常比你在本身的客戶機應用程序中計算要快得多。
前面已經學習了SQL彙集函數來彙總數據。可是,好比:要求出學生表中男生和女生各有多少人。可用使用兩條語句分別打印。下面介紹另外一種方式:分組。
分組:把數據分爲多個邏輯組,以便能對每一個組進行彙集計算。
分組時在SELECT語句的GROUP BY子句中創建的。按照上面的例子,對學生表的男女生分組:
SELECT ssex, COUNT(ssex) AS total FROM student GROUP BY ssex;
輸出:
+---------+----------------+ | stu_sex | total | +---------+----------------+ | 女 | 6 | | 男 | 11 | +---------+----------------+ 3 rows in set (0.05 sec)
可是也可這樣使用:
SELECT ssex, COUNT(*) AS total FROM student GROUP BY ssex;
輸出結果同上。
爲何會這樣??由於使用了GROUP BY,就沒必要指定要計算和估值得每一個組了。系統會自動完成。GROUP BY子句指示MySQL分組數據,而後對每一個組而不是整個結果集進行彙集。
在具體使用GROUP BY子句前,須要知道一些重要的規定:
使用WITH ROLLUP關鍵字,能夠獲得每一個分組以及每一個分組彙總級別(針對每一個分組)的值
好比:
SELECT ssex, COUNT(*) AS total FROM student GROUP BY ssex WITH ROLLUP;
輸出:
+---------+-------+ | stu_sex | total | +---------+-------+ | 女 | 10 | | 男 | 16 | | NULL | 26 | +---------+-------+ 3 rows in set (0.05 sec)
引入一個函數:IFNULL(expression, alt_value):IFNULL() 函數用於判斷第一個表達式是否爲 NULL,若是爲 NULL 則返回第二個參數的值,若是不爲 NULL 則返回第一個參數的值。
SELECT IFNULL(ssex,'總計') AS ssex, COUNT(*) AS total FROM student GROUP BY ssex WITH ROLLUP;
輸出:
+---------+-------+ | stu_sex | total | +---------+-------+ | 女 | 10 | | 男 | 16 | | 總計 | 26 | +---------+-------+ 3 rows in set (0.05 sec)
MySQL容許過濾分組,規定包括哪些分組,排除哪些分組。可是WHERE子句過濾指定的是行而不是分組。因此MySQL提供了HAVING子句,HAVING子句相似於WHERE,至今爲止的全部類型的WHERE子句均可以用HAVING子句來替代。惟一的差異是WHERE子句過濾行,而HAVING子句過濾分組(便是先分組再過濾)。
好比:顯示學生表的男生或者女生人數大於15個的。
SELECT ssex, COUNT(*) AS total FROM student GROUP BY ssex HAVING COUNT(*)>=15;
注意:HAVING子句在GROUP BY以後,由於是對分組的結果進行過濾。而WHERE子句是對行進行過濾,因此必須在GROUP BY以前。因此WHERE子句過濾的行可能會影響到GROUP BY的分組結果。
那麼能夠同時使用WHERE子句和HAVING子句嗎??答案是能夠的。
說一說排序(ORDER BY)和分組(GROUP BY)的區別:
排序 | 分組 |
---|---|
排序產生的輸出 | 輸出可能不是分組的順序 |
任意列均可以使用(甚至非選擇的列也可使用) | 只能使用選擇列或表達式列,並且必須使用每一個選擇列表達式 |
不必定須要 | 若是與彙集函數一塊兒使用列(或表達式),則必須使用 |
上面表格的第一行,能夠常常發現GROUP BY分組的數據確實是以分組順序輸出的,但狀況並不總這樣,它並非SQL規範所要求的。此外,用戶可能會要求以不一樣於分組的順序排序。僅由於你以某種方式分組數據,並不表示你須要以相同的方式排序輸出。應該提供明確的BRDER BY子句,即便其效果等同於GROUP BY子句的輸出結果。
因此通常使用GROUP BY子句最好跟上ORDER BY子句。
那麼在位置如何放置:ORDER BY子句必定是放在sQL語句最後的。
因此修改上面的語句:例子舉得不是很好,就看看怎麼寫。
SELECT ssex, COUNT(*) AS total FROM student GROUP BY ssex HAVING COUNT(*)>=15 ORDER BY ssex;
小結:學習瞭如何用SQL彙集函數對數據進行彙總計算。也介紹如何使用GROUP UP子句對數據組進行這些彙總金酸,返回每一個組的結果。並且還學了HAVING子句過濾特定的組,WHERE和HAVING之間以及ORDER BY和GROUP BY之間的差別