1、聚合函數(aggregation function)---也就是組函數mysql
在一個行的集合(一組行)上進行操做,對每一個組給一個結果。sql
經常使用的組函數:函數
求平均值code |
|
統計行的數量排序 |
|
求最大值字符串 |
|
求最小值 |
|
求累加和 |
①每一個組函數接收一個參數
②默認狀況下,組函數忽略列值爲null的行,不參與計算
③有時,會使用關鍵字distinct剔除字段值重複的條數
注意:
1)當使用組函數的select語句中沒有group by子句時,中間結果集中的全部行自動造成一組,而後計算組函數;
2)組函數不容許嵌套,例如:count(max(…));
3)組函數的參數能夠是列或是函數表達式;
4)一個SELECT子句中可出現多個彙集函數。
實驗演示用表:
mysql> select * from salary_tab; +--------+---------+ | userid | salary | +--------+---------+ | 1 | 1000.00 | | 2 | 2000.00 | | 3 | 3000.00 | | 4 | NULL | | 5 | 1000.00 | +--------+---------+ 5 rows in set (0.00 sec)
mysql> use TENNIS
mysql> show tables; +-------------------+ | Tables_in_TENNIS | +-------------------+ | COMMITTEE_MEMBERS | | MATCHES | | PENALTIES | | PLAYERS | | TEAMS | +-------------------+ 5 rows in set (0.00 sec)
①count(*):返回表中知足where條件的行的數量
mysql> select count(*) from salary_tab where salary='1000'; +----------+
| count(*) |
+----------+
| 2 |
+----------+ mysql> select count(*) from salary_tab; #沒有條件,默認統計表數據行數 +----------+
| count(*) |
+----------+
| 5 |
+----------+
②count(列):返回列值非空的行的數量
mysql> select count(salary) from salary_tab; +---------------+
| count(salary) |
+---------------+
| 4 |
+---------------+
③count(distinct 列):返回列值非空的、而且列值不重複的行的數量
mysql> select count(distinct salary) from salary_tab; +------------------------+
| count(distinct salary) |
+------------------------+
| 3 |
+------------------------+
④count(expr):根據表達式統計數據
mysql> select * from TT; +------+------------+
| UNIT | DATE |
+------+------------+
| a | 2018-04-03 |
| a | 2017-12-12 |
| b | 2018-01-01 |
| b | 2018-04-03 |
| c | 2016-06-06 |
| d | 2018-03-03 |
+------+------------+
6 rows in set (0.00 sec) mysql> select UNIT as '單位', -> COUNT(TO_DAYS(DATE)=TO_DAYS(NOW()) or null) as '今日統計', -> COUNT(YEAR(DATE)=YEAR(NOW()) or null) as '今年統計'
-> from v_jjd -> group by JJDW; +------+----------+----------+
| 單位 | 今日統計 | 今年統計 |
+------+----------+----------+
| a | 1 | 1 |
| b | 1 | 2 |
| c | 0 | 0 |
| d | 0 | 1 |
+------+----------+----------+
4 rows in set (0.00 sec)
mysql> select max(salary) from salary_tab; +-------------+
| max(salary) |
+-------------+
| 3000.00 |
+-------------+ mysql> select min(salary) from salary_tab; +-------------+
| min(salary) |
+-------------+
| 1000.00 |
+-------------+
注意:若是統計的列中只有NULL值,那麼MAX和MIN就返回NULL
!!表中列值爲null的行不參與計算
mysql> select sum(salary) from salary_tab; +-------------+
| sum(salary) |
+-------------+
| 7000.00 |
+-------------+ mysql> select avg(salary) from salary_tab; +-------------+
| avg(salary) |
+-------------+
| 1750.000000 |
+-------------+ mysql> select avg(ifnull(salary,0)) from salary_tab; +-----------------------+
| avg(ifnull(salary,0)) |
+-----------------------+
| 1400.000000 |
+-----------------------+
注意:要想列值爲NULL的行也參與組函數的計算,必須使用IFNULL函數對NULL值作轉換。
2、分組SELECT
SELECT select_expr [, select_expr ...] [FROM table_references [PARTITION partition_list] [WHERE where_condition] [GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_condition] [ORDER BY {col_name | expr | position} [ASC | DESC], ...] [LIMIT {[offset,] row_count | row_count OFFSET offset}]
分組SELECT的基本格式:
select [聚合函數] 字段名 from 表名
[where 查詢條件]
[group by 字段名]
[having 過濾條件]
一、group by子句
根據給定列或者表達式的每個不一樣的值將表中的行分紅不一樣的組,使用組函數返回每一組的統計信息
規則:
①出如今SELECT子句中的單獨的列,必須出如今GROUP BY子句中做爲分組列
②分組列能夠不出如今SELECT子句中
③分組列可出如今SELECT子句中的一個複合表達式中
④若是GROUP BY後面是一個複合表達式,那麼在SELECT子句中,它必須總體做爲一個表達式的一部分才能使用。
1)指定一個列進行分組
mysql> select salary,count(*) from salary_tab -> where salary>=2000
-> group by salary; +---------+----------+
| salary | count(*) |
+---------+----------+
| 2000.00 | 1 |
| 3000.00 | 1 |
+---------+----------+
2)指定多個分組列,‘大組中再分小組’
mysql> select userid,count(salary) from salary_tab -> where salary>=2000
-> group by salary,userid; +--------+---------------+
| userid | count(salary) |
+--------+---------------+
| 2 | 1 |
| 3 | 1 |
+--------+---------------+
3)根據表達式分組
mysql> select year(payment_date),count(*) -> from PENALTIES -> group by year(payment_date); +--------------------+----------+
| year(payment_date) | count(*) |
+--------------------+----------+
| 1980 | 3 |
| 1981 | 1 |
| 1982 | 1 |
| 1983 | 1 |
| 1984 | 2 |
+--------------------+----------+
5 rows in set (0.00 sec)
4)帶有排序的分組:若是分組列和排序列相同,則能夠合併group by和order by子句
mysql> select teamno,count(*) -> from MATCHES -> group by teamno -> order by teamno desc; +--------+----------+
| teamno | count(*) |
+--------+----------+
| 2 | 5 |
| 1 | 8 |
+--------+----------+
2 rows in set (0.00 sec) mysql> select teamno,count(*) -> from MATCHES -> group by teamno desc; #能夠把desc(或者asc)包含到group by子句中簡化 +--------+----------+
| teamno | count(*) |
+--------+----------+
| 2 | 5 |
| 1 | 8 |
+--------+----------+
2 rows in set (0.00 sec)
對於分組聚合注意:
經過select在返回集字段中,這些字段要麼就要包含在group by語句後面,做爲分組的依據,要麼就要被包含在聚合函數中。咱們能夠將group by操做想象成以下的一個過程:首先系統根據select語句獲得一個結果集,而後根據分組字段,將具備相同分組字段的記錄歸併成了一條記錄。這個時候剩下的那些不存在與group by語句後面做爲分組依據的字段就頗有可能出現多個值,可是目前一種分組狀況只有一條記錄,一個數據格是沒法放入多個數值的,因此這個時候就須要經過必定的處理將這些多值的列轉化成單值,而後將其放在對應的數據格中,那麼完成這個步驟的就是前面講到的聚合函數,這也就是爲何這些函數叫聚合函數了。
二、GROUP_CONCAT()函數
函數的值等於屬於一個組的指定列的全部值,以逗號隔開,而且以字符串表示。
例1:對於每一個球隊,獲得其編號和全部球員的編號
mysql> select teamno,group_concat(playerno) -> from MATCHES -> group by teamno; +--------+------------------------+
| teamno | group_concat(playerno) |
+--------+------------------------+
| 1 | 6,6,6,44,83,2,57,8 |
| 2 | 27,104,112,112,8 |
+--------+------------------------+
2 rows in set (0.01 sec)
若是沒有group by子句,group_concat返回一列的全部值
例2:獲得全部的罰款編號列表
mysql> select group_concat(paymentno) -> from PENALTIES; +-------------------------+
| group_concat(paymentno) |
+-------------------------+
| 1,2,3,4,5,6,7,8 |
+-------------------------+
1 row in set (0.00 sec)
三、with rollup子句:用來要求在一條group by子句中進行多個不一樣的分組
用的比較少點,可是有時能夠根據具體的需求使用
若是有子句GROUP BY E1,E2,E3,E4 WITH ROLLUP
那麼將分別執行如下分組:[E1,E2,E3,E4]、[E1,E2,E3]、[E1,E2]、[E1]、[]
注意:[ ]表示全部行都分在一組中
示例:按照球員的性別和居住城市,統計球員的總數;統計每一個性別球員的總數;統計全部球員的總數
mysql> select sex,town,count(*) -> from PLAYERS -> group by sex,town with rollup; +-----+-----------+----------+
| sex | town | count(*) |
+-----+-----------+----------+
| F | Eltham | 2 |
| F | Inglewood | 1 |
| F | Midhurst | 1 |
| F | Plymouth | 1 |
| F | NULL | 5 |
| M | Douglas | 1 |
| M | Inglewood | 1 |
| M | Stratford | 7 |
| M | NULL | 9 |
| NULL | NULL | 14 |
+-----+-----------+----------+
10 rows in set (0.00 sec)
四、HAVING子句:對分組結果進行過濾
注意:
不能使用WHERE子句對分組後的結果進行過濾
不能在WHERE子句中使用組函數,僅用於過濾行
mysql> select playerno -> from PENALTIES -> where count(*)>1
-> group by playerno; ERROR 1111 (HY000): Invalid use of group function
由於WHERE子句比GROUP BY先執行,而組函數必須在分完組以後才執行,且分完組後必須使用having子句進行結果集的過濾。
基本語法:
SELECT select_expr [, select_expr ...] FROM table_name [WHERE where_condition] [GROUP BY {col_name | expr} [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_condition]
!!!having子語句與where子語句區別:
where子句在分組前對記錄進行過濾;
having子句在分組後對記錄進行過濾
mysql> select salary,count(*) from salary_tab -> where salary>=2000
-> group by salary -> having count(*)>=0; +---------+----------+
| salary | count(*) |
+---------+----------+
| 2000.00 | 1 |
| 3000.00 | 1 |
+---------+----------+
1)HAVING能夠單獨使用而不和GROUP BY配合,若是隻有HAVING子句而沒有GROUP BY,表中全部的行分爲一組
2)HAVING子句中可使用組函數
3)HAVING子句中的列,要麼出如今一個組函數中,要麼出如今GROUP BY子句中(不然出錯)
mysql> select town,count(*) -> from PLAYERS -> group by town -> having birth_date>'1970-01-01'; ERROR 1054 (42S22): Unknown column 'birth_date' in 'having clause' mysql> select town,count(*) -> from PLAYERS -> group by town -> having town in ('Eltham','Midhurst'); +----------+----------+
| town | count(*) |
+----------+----------+
| Eltham | 2 |
| Midhurst | 1 |
+----------+----------+
2 rows in set (0.00 sec)
3、集合查詢操做
union用於把兩個或者多個select查詢的結果集合併成一個
SELECT ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | DISTINCT] SELECT ...]
默認狀況下,UNION = UNION DISTINCT
①進行合併的兩個查詢,其SELECT列表必須在數量和對應列的數據類型上保持一致;
②默認會去掉兩個查詢結果集中的重複行;默認結果集不排序;
③最終結果集的列名來自於第一個查詢的SELECT列表
UNION ALL不去掉結果集中重複的行
注:聯合查詢結果使用第一個select語句中的字段名
mysql> select * from t1; +------+------+
| num | addr |
+------+------+
| 123 | abc |
| 321 | cba |
+------+------+
2 rows in set (0.00 sec) mysql> select * from t2; +------+------+
| id | name |
+------+------+
| 1 | a |
| 2 | A |
+------+------+
2 rows in set (0.00 sec) mysql> select * from t1 -> union -> select * from t2; +------+------+
| num | addr |
+------+------+
| 123 | abc |
| 321 | cba |
| 1 | a |
| 2 | A |
+------+------+
4 rows in set (0.00 sec)
若是要對合並後的整個結果集進行排序,ORDER BY子句只能出如今最後面的查詢中
注意:
在去重操做時,若是列值中包含NULL值,認爲它們是相等的