MySql中的資料查詢語言(DQL)二:分組函式/聚合函式/多行處理函式和分組查詢
技術標籤:C_資料庫階段C1_MySql資料庫mysqljava
一、分組函式/聚合函式/多行處理函式
1、概念
分組函式一共5個。分組函式自動忽略NULL
分組函式還有另一個名字:多行處理函式。
多行處理函式的特點: 輸入多行,最終輸出的結果是1行
記住:所有的分組函式都是對“某一組”資料進行操作的。
2、說明
注意:分組函式自動忽略空值,不需要手動的加where條件排除空值。
select count(*) from emp where xxx;符合條件的所記錄總數。
select count(comm) from emp; comm這個欄位中不為空的元素總數。
注意:分組函式不能直接使用在where關鍵字後面
select ename,sal from emp where sal > avg(sal); //ERROR 1111 (HY000): Invalid use of group function
思考以上的錯誤資訊:無效的使用了分組函式?
原因:SQL語句當中有一個語法規則,分組函式不可直接使用在where子句當中。why???
怎麼解釋?
因為group by是在where執行之後才會執行的。
3、count
count(*)和count(具體的某個欄位),他們有什麼區別?
count(*): 不是統計某個欄位中資料的個數,而是統計總記錄條數。(和某個欄位無關)
count(comm):
舉例:
取得所有的員工數
Count(*)表示取得所有記錄,忽略null,為null的值也會取得
mysql> select count(*) from emp;
±---------+
| count(*) |
±---------+
| 14 |
±---------+
1 row in set (0.05 sec)
取得津貼不為null員工數
mysql> select count(comm) from emp;
±------------+
| count(comm) |
| 4 |
±------------+
1 row in set (0.00 sec)
採用count(欄位名稱),不會取得為null的記錄
4、sum:可以取得某一個列的和,null會被忽略
找出工資總和?
select sum(sal) from emp;
取得津貼的合計
select sum(comm) from emp where comm is not null;// 不需要額外新增這個過濾條件。sum函式自動忽略NULL。
取得薪水的合計(sal+comm)
select sum(sal+comm) from emp;//錯誤的,原因在於comm欄位null值,所以無法計算,sum會忽略掉,正確的做法是將comm欄位轉換成0
select sum(sal+IFNULL(comm, 0)) from emp;
5、單行處理函式:
什麼是單行處理函式?
輸入一行,輸出一行。
舉例:
計算每個員工的年薪?
select ename,(sal+comm)*12 as yearsal from emp;
重點:所有資料庫都是這樣規定的,只要有NULL參與的運算結果一定是NULL。
使用ifnull函式:
select ename,(sal+ifnull(comm,0))*12 as yearsal from emp;
ifnull() 空處理函式?
ifnull(可能為NULL的資料,被當做什麼處理) : 屬於單行處理函式。
select ename,ifnull(comm,0) as comm from emp;
6、avg:取得某一列的平均值
舉例:
取得平均薪水
select avg(sal) from emp;
找出工資高於平均工資的員工?
select ename,sal from emp where sal > avg(sal); //ERROR 1111 (HY000): Invalid use of group function
思考以上的錯誤資訊:無效的使用了分組函式?
原因:SQL語句當中有一個語法規則,分組函式不可直接使用在where子句當中。why???
怎麼解釋?
因為group by是在where執行之後才會執行的。
select 5
..
from 1
..
where 2
..
group by 3
..
having 4
..
order by 6
..
正確的:
第一步:找出平均工資
select avg(sal) from emp;
±------------+
| avg(sal) |
±------------+
| 2073.214286 |
±------------+
第二步:找出高於平均工資的員工
select ename,sal from emp where sal > 2073.214286;
select ename,sal from emp where sal > (select avg(sal) from emp);
7、max:取得某個一列的最大值
舉例:
找出最高薪水的員工
mysql> select ename,sal from emp where sal = (select max(sal) from emp);
取得最高薪水
mysql> select max(sal) from emp;
取得最晚入職得員工
mysql> select max(hiredate) from emp;
8、min:取得某個一列的最小值
舉例:
取得最低薪水
mysql> select min(sal) from emp;
取得最早入職得員工(可以不使用str_to_date轉換)
mysql> select min(str_to_date(hiredate, '%Y-%m-%d')) from emp;
±---------------------------------------+
| min(str_to_date(hiredate, ‘%Y-%m-%d’)) |
±---------------------------------------+
| 1980-12-17 |
±---------------------------------------+
1 row in set (0.04 sec)
9、組合聚合函式
可以將這些聚合函式都放到select中一起使用
mysql> select count(*),sum(sal),avg(sal),max(sal),min(sal) from emp;
±---------±---------±------------±---------±---------+
| count(*) | sum(sal) | avg(sal) | max(sal) | min(sal) |
±---------±---------±------------±---------±---------+
| 14 | 29025.00 | 2073.214286 | 5000.00 | 800.00 |
±---------±---------±------------±---------±---------+
1 row in set (0.00 sec)
二、分組查詢
分組查詢主要涉及到兩個子句,分別是:group by和having
1、group by:
按照某個欄位或者某些欄位進行分組。
舉例:
取得每個工作崗位的工資合計,要求顯示崗位名稱和工資合計
mysql> select job,sum(sal) as sumSal from emp group by job;
案例:找出每個工作崗位的最高薪資。
mysql> select job,max(sal) from emp group by job;
每個工作崗位的平均薪資?
select job,avg(sal) from emp group by job;
多個欄位能不能聯合起來一塊分組?
案例:找出每個部門不同工作崗位的最高薪資。
mysql> select max(sal),job,deptno from emp group by deptno,job;
注意:分組函式一般都會和group by聯合使用,這也是為什麼它被稱為分組函式的原因。並且任何一個分組函式(count sum avg max min)都是在group by語句執行結束之後才會執行的。當一條sql語句沒有group by的話,整張表的資料會自成一組。
select ename,max(sal),job from emp group by job;
以上在mysql當中,查詢結果是有的,但是結果沒有意義,在Oracle資料庫當中會報錯。語法錯誤。
Oracle的語法規則比MySQL語法規則嚴謹。
記住一個規則:當一條語句中有group by的話,select後面只能跟分組函式和參與分組的欄位。
2、having :
having是對分組之後的資料進行再次過濾。
舉例:
找出每個部門的最高薪資,要求顯示薪資大於2900的資料。
第一步:找出每個部門的最高薪資
select max(sal),deptno from emp group by deptno;
±---------±-------+
| max(sal) | deptno |
±---------±-------+
| 5000.00 | 10 |
| 3000.00 | 20 |
| 2850.00 | 30 |
±---------±-------+
第二步:找出薪資大於2900
select max(sal),deptno from emp group by deptno having max(sal) > 2900; // 這種方式效率低。
±---------±-------+
| max(sal) | deptno |
±---------±-------+
| 5000.00 | 10 |
| 3000.00 | 20 |
±---------±-------+
select max(sal),deptno from emp where sal > 2900 group by deptno; // 效率較高,建議能夠使用where過濾的儘量使用where。
找出每個部門的平均薪資,要求顯示薪資大於2000的資料。
第一步:找出每個部門的平均薪資
select deptno,avg(sal) from emp group by deptno;
第二步:要求顯示薪資大於2000的資料
select deptno,avg(sal) from emp group by deptno having avg(sal) > 2000;
where後面不能使用分組函式:
select deptno,avg(sal) from emp where avg(sal) > 2000 group by deptno; // 錯誤了。
這種情況只能使用having過濾。
3、select語句總結
總結一個完整的DQL語句怎麼寫?
select 5
..
from 1
..
where 2
..
group by 3
..
having 4
..
order by 6
..
一個完整的select語句格式如下
select 欄位
from 表名
where …….
group by ………
having …….(就是為了過濾分組後的資料而存在的—不可以單獨的出現)
order by ………
以上語句的執行順序
首先執行where語句過濾原始資料
執行group by進行分組
執行having對分組資料進行操作
執行select出資料
執行order by排序
原則:能在where中過濾的資料,儘量在where中過濾,效率較高。having的過濾是專門對分組之後的資料進行過濾的。
4.distinct:關於查詢結果集的去重
舉例:
mysql> select distinct job from emp; // distinct關鍵字去除重複記錄。
±----------+
| job |
±----------+
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
±----------+
mysql> select ename,distinct job from emp;
以上的sql語句是錯誤的。
記住:distinct只能出現在所有欄位的最前面。
mysql> select distinct deptno,job from emp;//去重deptno與job兩相連相同的
±-------±----------+
| deptno | job |
±-------±----------+
| 20 | CLERK |
| 30 | SALESMAN |
| 20 | MANAGER |
| 30 | MANAGER |
| 10 | MANAGER |
| 20 | ANALYST |
| 10 | PRESIDENT |
| 30 | CLERK |
| 10 | CLERK |
±-------±----------+
案例:統計崗位的數量?
select count(distinct job) from emp;
±--------------------+
| count(distinct job) |
±--------------------+
| 5 |
±--------------------+