文章目錄
- 前言 🥑
- 🥝 聚合函數
- 🍓 COUNT( ) 查詢數據數量
- 🍓 SUM( ) 查詢數據總和
- 🍓 AVG( ) 查詢數據平均值
- 🍓 MAX( ) 查詢數據最大值
- 🍓 MIN( ) 查詢數據最小值
- 🥝 數據分組GROUP BY子句
- 🍓 GROUP BY示例
- 🍓 HAVING語句
前言 🥑
在MySQL中存在一種查詢方式叫做聚合查詢;
聚合查詢顧名思義就是將一組數據的同種類型進行聚合,那么既然是一組同類型的數據那么即必須要對該數據進行分組同時再對這組數據進行聚合;
所以對于聚合查詢來說時應該有兩部分組合:
- 將數據進行分組;
- 將數據進行聚合統計;
需要配合SELECT
語句進行使用;
🥝 聚合函數
在MySQL中存在一些高頻操作:查詢數量個數,查詢數據總和…
而在MySQL中存在著一些函數,這些函數即用來對表內數據進行這些比較高頻的操作,這些函數叫做聚合函數,當然這些函數存在的意義也是聚合查詢中的重要操作;
存在一張表(Point)
:
+----+---------+---------+------+---------+
| id | name | chinese | math | english |
+----+---------+---------+------+---------+
| 1 | Lihua | 100 | 118 | 180 |
| 2 | Liming | 57 | 58 | 140 |
| 3 | Zhaolao | 66 | 80 | 94 |
| 4 | Wu | 76 | 70 | 94 |
| 5 | Wuqi | 88 | 43 | 160 |
| 6 | Liqiang | 89 | 122 | 180 |
| 7 | Qinsu | 90 | 104 | 134 |
| 8 | Zhaoli | 54 | 74 | 200 |
+----+---------+---------+------+---------+
🍓 COUNT( ) 查詢數據數量
語法:
COUNT([DISTINCT] expr)
-- 返回查詢到的數據的數量
-- 其中[]內為可選項
該函數能查詢對應數據的數量;
- 示例1:查詢該表中人數個數:
mysql> select count(*) from Point; +----------+ | count(*) | +----------+ | 8 | +----------+ 1 row in set (0.00 sec)
- 示例2:查詢該表中
math
字段數據>100的個數:mysql> select count(math) from Point where math>100; +-------------+ | count(math) | +-------------+ | 3 | +-------------+ 1 row in set (0.00 sec)
- 示例3:查詢該表中
english
字段數據個數mysql> select count(distinct english) from Point; -- 利用distinct進行去重 +-------------------------+ | count(distinct english) | +-------------------------+ | 6 | +-------------------------+ 1 row in set (0.00 sec)
🍓 SUM( ) 查詢數據總和
語法:
COUNT([DISTINCT] expr)
該函數能夠算出一組數據的總和;
- 示例:計算出
english
字段所有數據的總和:mysql> select sum(english) from Point; +--------------+ | sum(english) | +--------------+ | 1182 | +--------------+ 1 row in set (0.00 sec)mysql> select sum(distinct english) from Point; +-----------------------+ | sum(distinct english) | +-----------------------+ | 908 | +-----------------------+ 1 row in set (0.00 sec)
🍓 AVG( ) 查詢數據平均值
語法:
AVG([DISTINCT] expr)
該函數能夠算出一組數據的平均值;
- 示例:計算出表中
english+math+chinese
字段的平均值:mysql> select AVG(english+chinese+math) from Point; +---------------------------+ | AVG(english+chinese+math) | +---------------------------+ | 308.8750 | +---------------------------+ 1 row in set (0.00 sec)
🍓 MAX( ) 查詢數據最大值
語法:
MAX([DISTINCT] expr)
該函數能夠算出一組數據的最大值;
- 示例:計算出表中
chinese
字段的最大值:mysql> select max(chinese) from Point; +--------------+ | max(chinese) | +--------------+ | 100 | +--------------+ 1 row in set (0.00 sec)
🍓 MIN( ) 查詢數據最小值
語法:
MIN([DISTINCT] expr)
該函數能夠算出一組數據的最小值(用法與MAX()
函數相同);
🥝 數據分組GROUP BY子句
聚合統計講究的是一個先將數據進行分組在將數據進行聚合統計,在MySQL中可以使用GPOUP BY
子句將數據進行分組;
在SELECT
中使用GROUP BY
子句對指定列進行分組查詢;
語法:
SELECT column1 ,column2, ... FROM table_name GROUP BY column1,column2...;
在進行聚合查詢的演示前需要準備一個來自Oralce 9i
的測試用表 - 雇員表(該表在本篇博客中存在資源);
下載該表后使用
SOURCE /路徑
的方式將表至于MySQL當中;
該文件為一個數據庫,庫中共有三張表: dept部門表
,emp員工表
,salgrade工資等級表
;
其中三張表的表結構分別為:
-
dept
Table: dept Create Table: CREATE TABLE `dept` (`deptno` int(2) unsigned zerofill NOT NULL COMMENT ' 部門編號 ',`dname` varchar(14) DEFAULT NULL COMMENT ' 部門名稱 ',`loc` varchar(13) DEFAULT NULL COMMENT ' 部門所在地點 ' ) ENGINE=MyISAM DEFAULT CHARSET=utf8
-
emp
Table: emp Create Table: CREATE TABLE `emp` (`empno` int(6) unsigned zerofill NOT NULL COMMENT '雇員編號',`ename` varchar(10) DEFAULT NULL COMMENT '雇員姓名',`job` varchar(9) DEFAULT NULL COMMENT '雇員職位',`mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇員領導編號',`hiredate` datetime DEFAULT NULL COMMENT '雇傭時間',`sal` decimal(7,2) DEFAULT NULL COMMENT '工資月薪',`comm` decimal(7,2) DEFAULT NULL COMMENT '獎金',`deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部門編號' ) ENGINE=MyISAM DEFAULT CHARSET=utf8
salgrade
Table: salgrade Create Table: CREATE TABLE `salgrade` (`grade` int(11) DEFAULT NULL COMMENT '等級',`losal` int(11) DEFAULT NULL COMMENT '此等級最低工資',`hisal` int(11) DEFAULT NULL COMMENT '此等級最高工資' ) ENGINE=MyISAM DEFAULT CHARSET=utf8
該表的對應數據分別為:
############## 表dept ##############
mysql> select * from dept;
+--------+------------+----------+
| deptno | dname | loc |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+############## 表emp ##############
mysql> select * from emp;
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| 007369 | SMITH | CLERK | 7902 | 1980-12-17 00:00:00 | 800.00 | NULL | 20 |
| 007499 | ALLEN | SALESMAN | 7698 | 1981-02-20 00:00:00 | 1600.00 | 300.00 | 30 |
| 007521 | WARD | SALESMAN | 7698 | 1981-02-22 00:00:00 | 1250.00 | 500.00 | 30 |
| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL | 20 |
| 007654 | MARTIN | SALESMAN | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 |
| 007698 | BLAKE | MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL | 30 |
| 007782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL | 10 |
| 007788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL | 20 |
| 007839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL | 10 |
| 007844 | TURNER | SALESMAN | 7698 | 1981-09-08 00:00:00 | 1500.00 | 0.00 | 30 |
| 007876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL | 20 |
| 007900 | JAMES | CLERK | 7698 | 1981-12-03 00:00:00 | 950.00 | NULL | 30 |
| 007902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL | 20 |
| 007934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 | NULL | 10 |
+--------+--------+-----------+------+---------------------+---------+---------+--------+############## 表salgrade ##############
mysql> select * from salgrade;
+-------+-------+-------+
| grade | losal | hisal |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+
🍓 GROUP BY示例
-
顯示每個部門的最高工資與平均工資:
該在示例中需要顯示每個每個部門的最高工資,說明需要將 每個部分進行分組, 即
GROUP BY deptno
;
同時要求計算出每個部門的最高工資與最低工資,說明需要對每個部門進行聚合統計,即MAX(sal)
與AVG(sal)
;
將其組合即為:select max(sal),avg(sal) from emp group by deptno;
由于是以
deptno
進行分組,所以可以SELECT
出分組的名;
即:mysql> select deptno,max(sal),avg(sal) from emp group by deptno; +--------+----------+-------------+ | deptno | max(sal) | avg(sal) | +--------+----------+-------------+ | 10 | 5000.00 | 2916.666667 | | 20 | 3000.00 | 2175.000000 | | 30 | 2850.00 | 1566.666667 | +--------+----------+-------------+
-
顯示每個部門的每種崗位的平均工資與最低工資:
在該示例中需要顯示每個部門與每種崗位,說明該示例中需要對數據進行兩類分組,即為
GROUP BY deptno , job
;
且需要聚合統計出該類數據的平均值與最高值,即為AVG(sal)
與MIN(sal)
;
在該條件中由于是對部門deptno
與崗位job
進行分組,所以在SELECT
時可以分別顯示出他們的值;
即為:mysql> SELECT deptno,job,avg(sal),min(sal) from emp group by deptno,job; +--------+-----------+-------------+----------+ | deptno | job | avg(sal) | min(sal) | +--------+-----------+-------------+----------+ | 10 | CLERK | 1300.000000 | 1300.00 | | 10 | MANAGER | 2450.000000 | 2450.00 | | 10 | PRESIDENT | 5000.000000 | 5000.00 | | 20 | ANALYST | 3000.000000 | 3000.00 | | 20 | CLERK | 950.000000 | 800.00 | | 20 | MANAGER | 2975.000000 | 2975.00 | | 30 | CLERK | 950.000000 | 950.00 | | 30 | MANAGER | 2850.000000 | 2850.00 | | 30 | SALESMAN | 1400.000000 | 1250.00 | +--------+-----------+-------------+----------+ 9 rows in set (0.00 sec)# 也可將其進行重命名 mysql> SELECT deptno 部門,job 崗位,avg(sal) 最大工資,min(sal) 最小工資 from emp group by deptno,job; +--------+-----------+--------------+--------------+ | 部門 | 崗位 | 最大工資 | 最小工資 | +--------+-----------+--------------+--------------+ | 10 | CLERK | 1300.000000 | 1300.00 | | 10 | MANAGER | 2450.000000 | 2450.00 | | 10 | PRESIDENT | 5000.000000 | 5000.00 | | 20 | ANALYST | 3000.000000 | 3000.00 | | 20 | CLERK | 950.000000 | 800.00 | | 20 | MANAGER | 2975.000000 | 2975.00 | | 30 | CLERK | 950.000000 | 950.00 | | 30 | MANAGER | 2850.000000 | 2850.00 | | 30 | SALESMAN | 1400.000000 | 1250.00 | +--------+-----------+--------------+--------------+ 9 rows in set (0.00 sec)
🍓 HAVING語句
HAVING
語句為條件篩選語句的一種,其使用方式類似于WHERE
;
大部分情況下HAVING
子句是用來配合GROUP BY
語句進行使用,即對分組聚合后的數據進行篩選;
HAVING
子句可以做到與WHERE
子句一樣的事,但是WHERE
子句的功能卻不能與HAVING
子句相當;
由于HAVING
語句是用來針對聚合統計而產生的,所以在MySQL中不能使用HAVING
子句來代替WHERE
子句,即這兩個語句不能混為一談;
-
示例:顯示平均工資低于2000的部門和它的平均工資:
在該示例中要求了
平均工資低于2000的部門
,即需要對部門進行GROUP BY
分類,即GROUP BY deptno
;
同時示例要求顯示平均工資,即為AVG(sal)
;
將其組合在一起即能顯示出各個部門的平均工資:mysql> select deptno,avg(sal) from emp group by deptno; +--------+-------------+ | deptno | avg(sal) | +--------+-------------+ | 10 | 2916.666667 | | 20 | 2175.000000 | | 30 | 1566.666667 | +--------+-------------+ 3 rows in set (0.00 sec)
其又要求顯示平均工資低于2000的部門與它的平均工資,則可以使用
HAVING
子句對聚合統計后的數據進行篩選;mysql> select deptno as 部門,avg(sal) as 平均工資 from emp group by deptno having 平均工資<2000; +--------+--------------+ | 部門 | 平均工資 | +--------+--------------+ | 30 | 1566.666667 | +--------+--------------+ 1 row in set (0.00 sec)##當使用where子句代替having子句時將會報錯; mysql> select deptno as 部門,avg(sal) as 平均工資 from emp group by deptno where 平均工資<2000; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where 平均工資<2000' at line 1