MySQL最常用分組聚合函數


一、聚合函數aggregation function---也就是組函數

  在一個行的集合(一組行)上進行操作,對每個組給一個結果。

常用的組函數:

AVG([distinct] expr)

求平均值

COUNT({*|[distinct] } expr)

統計行的數量

MAX([distinct] expr)

求最大值

MIN([distinct] expr)

求最小值

SUM([distinct] expr)

求累加和

  ①每個組函數接收一個參數

  ②默認情況下,組函數忽略列值為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)

 

1、count函數

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

 

2、max和min函數---統計列中的最大最小值

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

 

3、sum和avg函數---求和與求平均

!!表中列值為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值做轉換

 

 

二、分組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 過濾條件]

1、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語句后面作為分組依據的字段就很有可能出現多個值,但是目前一種分組情況只有一條記錄,一個數據格是無法放入多個數值的,所以這個時候就需要通過一定的處理將這些多值的列轉化成單值,然后將其放在對應的數據格中,那么完成這個步驟的就是前面講到的聚合函數,這也就是為什么這些函數叫聚合函數了。

 

2、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)

 

3、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)

 

4、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)

 

 

三、集合查詢操作

  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值,認為它們是相等的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM