Py学习  »  DATABASE

MySQL基础05-分组与聚合(DQL语句)

四月不见 • 2 年前 • 537 次点击  

一、聚合函数(组函数)

在某个组的集合上进行操作,对每个组给出一个结果。

常用的聚合函数:

函数 描述
avg([distinct] 字段) 求平均值
count({*|[distinct] } 字段) 统计行的数量
max([distinct] 字段) 求最大值
min([distinct] 字段) 求最小值
sum([distinct] 字段) 求累加和

①每个聚合函数接收一个参数
②默认情况下,聚合函数忽略列值为null的行,不参与计算
③有时,会使用关键字distinct剔除字段值重复的条数

注意:
1)当使用聚合函数的select语句中没有group by子句时,查询结果集中的所有行自动形成一组,然后计算聚合函数;
2)聚合函数不允许嵌套,例如:count(max(…));
3)聚合函数的参数可以是列或是函数表达式;
4)一个SELECT子句中可出现多个聚集函数。

二、简单案例

测试用表:

mysql> select * from salary;
+---------+-------------+
| user_id | user_salary |
+---------+-------------+
|       1 |     1000.00 |
|       2 |     2000.00 |
|       3 |     3000.00 |
|       4 |        NULL |
|       5 |     1000.00 |
+---------+-------------+
5 rows in set (0.00 sec)

1、count函数

mysql> select count(*) from salary;   #没有条件,默认统计表数据行数
+----------+
| count(*) |
+----------+
|        5 |
+----------+
1 row in set (0.05 sec)

mysql> select count(user_salary) from salary;   #返回列值非空的行的数量
+--------------------+ 
| count(user_salary) |
+--------------------+
|                  4 |
+--------------------+
1 row in set (0.00 sec)

mysql> select count(distinct user_salary) from salary;
+-----------------------------+
| count(distinct user_salary) |
+-----------------------------+
|                           3 |    # 返回列值非空的、并且列值不重复的行的数量
+-----------------------------+
1 row in set (0.05 sec)

2、max和min函数

mysql> select max(user_salary) from salary;
+------------------+
| max(user_salary) |
+------------------+
|          3000.00 |
+------------------+
1 row in set (0.05 sec)

mysql> select min(user_salary) from salary;
+------------------+
| min(user_salary) |
+------------------+
|          1000.00 |
+------------------+
1 row in set (0.00 sec)

注意:如果统计的列中只有NULL值,那么MAX和MIN就返回NULL。

3、sum和avg函数

注意:表中列值为null的行不参与计算!!!

mysql> select sum(user_salary) from salary;
+------------------+
| sum(user_salary) |
+------------------+
|          7000.00 |
+------------------+
1 row in set (0.00 sec)

mysql> select avg(user_salary) from salary;
+------------------+
| avg(user_salary) |
+------------------+
|      1750.000000 |
+------------------+
1 row in set (0.00 sec)

mysql> select avg(ifnull(user_salary,0)) from salary; 
+----------------------------+
| avg(ifnull(user_salary,0)) |  #把值为null的行当做0加入计算。
+----------------------------+
|                1400.000000 |
+----------------------------+
1 row in set (0.00 sec)

4、注意

1)要想列值为NULL的行也参与聚合函数的计算,必须使用IFNULL函数对NULL值做转换。

2)不能使用WHERE子句对分组后的结果进行过滤(不能在WHERE子句中使用聚合函数)。
如下为错误示范:

#错误示例
mysql> select user_salary,count(*) num from salary where count(*) > 0 group by user_salary;  
ERROR 1111 (HY000): Invalid use of group function

三、分组 Group

分组查询的基本语法: select [聚合函数|分组列]... from 表名 [where 查询条件] [group by 分组列] [having 过滤条件]

1、group by子句

根据给定列或者表达式的每一个不同的值将表中的行分成不同的组,使用聚合函数返回每一组的统计信息

规则:
出现在SELECT子句中的单独的列,必须出现在GROUP BY子句中作为分组列
②分组列可以不出现在SELECT子句中
③分组列可出现在SELECT子句中的一个复合表达式中
④如果GROUP BY后面是一个复合表达式,那么在SELECT子句中,它必须整体作为一个表达式的一部分才能使用。

1)指定一个列进行分组

mysql> select user_salary,count(*) num from salary group by user_salary;
+-------------+-----+
| user_salary | num |
+-------------+-----+
|        NULL |   1 |
|     1000.00 |   2 |
|     2000.00 |   1 |
|     3000.00 |   1 |
+-------------+-----+
4 rows in set (0.00 sec)

2)指定多个分组列,‘大组中再分小组’

mysql> select user_salary,count(*) num from salary where user_salary > 0 group by user_salary,user_id;
+-------------+-----+
| user_salary | num |
+-------------+-----+
|     1000.00 |   1 |
|     1000.00 |   1 |
|     2000.00 |   1 |
|     3000.00 |   1 |
+-------------+-----+
4 rows in set (0.00 sec)

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

  • 通过select在返回集字段中,这些字段要么就要包含在group by语句后面,作为分组的依据,要么就要被包含在聚合函数中。
  • 我们可以将group by操作想象成如下的一个过程:首先系统根据select语句得到一个结果集,然后根据分组字段,将具有相同分组字段的记录归并成了一条记录。这个时候剩下的那些不存在与group by语句后面作为分组依据的字段就很有可能出现多个值,但是目前一种分组情况只有一条记录,一个数据格是无法放入多个数值的,所以这个时候就需要通过一定的处理将这些多值的列转化成单值,然后将其放在对应的数据格中,那么完成这个步骤的就是前面讲到的聚合函数,这也就是为什么这些函数叫聚合函数了。

2、group_concat() 函数

函数的值等于属于一个组的指定列的所有值,以逗号隔开,并且以字符串表示。

mysql> select group_concat(user_id),user_salary,count(*) from salary group by user_salary;
+-----------------------+-------------+----------+
| group_concat(user_id) | user_salary | count(*) |
+-----------------------+-------------+----------+
| 4                     |        NULL |        1 |
| 1,5                   |     1000.00 |        2 |
| 2                     |     2000.00 |        1 |
| 3                     |     3000.00 |        1 |
+-----------------------+-------------+----------+
4 rows in set (0.00 sec)

如果没有group by子句,group_concat返回一列的所有值:

mysql> select group_concat(user_id) from salary;
+-----------------------+
| group_concat(user_id) |
+-----------------------+
| 1,2,3,4,5             |
+-----------------------+
1 row in set (0.02 sec)

3、having子句:对分组后的结果进行过滤

having子语句与where子语句区别:
where子句在分组前对记录进行过滤;having子句在分组后对记录进行过滤。

语法: select [聚合函数|分组列]+ from 表名 [where 查询条件] [group by 分组列] [having 过滤条件]

mysql> select user_salary,count(*) from salary group by user_salary having count(*) > 1;
+-------------+----------+
| user_salary | count(*) |
+-------------+----------+
|     1000.00 |        2 |
+-------------+----------+
1 row in set (0.00 sec)

注意:
1)HAVING可以单独使用而不和GROUP BY配合,如果只有HAVING子句而没有GROUP BY,表中所有的行分为一组
2)HAVING子句中可以使用聚合函数
3)HAVING子句中的列,要么出现在一个聚合函数,要么出现在GROUP BY子句中(否则出错)

having 与 where 的区别:
1)having是在分组后对数据进行过滤
2)where是在分组前对数据进行过滤
3)having后面可以使用聚合函数
4)where后面不可以使用聚合函数

四、参考

8.0官方文档: https://dev.mysql.com/doc/refman/8.0/en/

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/126392
 
537 次点击  
文章 [ 1 ]  |  最新文章 2 年前
1106379167
Reply   •   1 楼
1106379167    2 年前

分享全网最稳回血技术计划【实力非凡】Q:✅7961508官网:uu02.cc✅ 问鼎中崋✅九五至尊✅超凡团队✅超越自己✅永不平凡✅诚信赢天下✅实力中崋✅业界帝一✅谁与争锋✅十年老品牌,欢迎你到来(根据中央新闻联播评价)来源中国中央电视台CCTV点评:不受天磨非好汉,不遭人妒是庸才