美文网首页数据库
MySQL基础04-常用分组聚合函数

MySQL基础04-常用分组聚合函数

作者: 四月不见 | 来源:发表于2019-03-12 22:17 被阅读1次

    一、聚合函数

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

    常用的组函数:

    函数 描述
    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;
    +---------+-------------+
    | 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)
    

    注意:要想列值为NULL的行也参与组函数的计算,必须使用IFNULL函数对NULL值做转换。

    二、分组SELECT

    分组SELECT的基本格式:

    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)带有排序的分组:如果分组列和排序列相同,则可以合并group by和order by子句

    对于分组聚合注意:
    通过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子句:对分组结果进行过滤

    注意:
    不能使用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
    

    基本语法:

    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 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子句中(否则出错)

    相关文章

      网友评论

        本文标题:MySQL基础04-常用分组聚合函数

        本文链接:https://www.haomeiwen.com/subject/skyopqtx.html