1. 程式人生 > 其它 >MySql中的資料查詢語言(DQL)二:分組函式/聚合函式/多行處理函式和分組查詢

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):

表示統計comm欄位中不為NULL的資料總數量。
舉例:
取得所有的員工數
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 |
±--------------------+