MySQL最常用分组聚合函数「建议收藏」

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值,认为它们是相等的

相关视频教程:

MySQL最常用分组聚合函数「建议收藏」

获取方式:进入公众号回复: mysql视频

MySQL最常用分组聚合函数「建议收藏」

(关注公众号,获取更多资源)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/112073.html原文链接:https://javaforall.net

(0)
上一篇 2022年2月10日 下午10:00
下一篇 2022年2月10日 下午10:00


相关推荐

  • 哈佛结构与普林斯顿结构_普林斯顿大学和哈佛大学哪个更厉害

    哈佛结构与普林斯顿结构_普林斯顿大学和哈佛大学哪个更厉害1. 冯·诺依曼结构   冯·诺依曼结构,又称为普林斯顿体系结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构。取指令和取操作数都在同一总线上,通过分时复用的方式进行;缺点是在高速运行时,不能达到同时取指令和取操作数,从而形成了传输过程的瓶颈。由于程序指令存储地址和数据存储地址指向同一个存储器的不同物理位置,因此程序指令和数据的宽度相同,如英特尔公司的8086中央处理器的程序指

    2022年10月5日
    3
  • Win10与Ubuntu 18.04双系统安装。(Win10引导Linux)[通俗易懂]

    Win10与Ubuntu 18.04双系统安装。(Win10引导Linux)[通俗易懂]作为菜鸟,为了满足我自己的求知欲,特别照着几篇大神教程装了一遍,给大家分享一下流程。1、win10安装(已安装请略过)1)系统U盘制作(参照微信公众号“软件安装管家”):http://mp.weixin.qq.com/s?__biz=MzIwMjE1MjMyMw==&mid=2650199025&idx=1&sn=49b0d9b6d9f02b68223f7a9f913cde…

    2022年7月24日
    23
  • MD5算法如何被激活成功教程

    MD5算法如何被激活成功教程小明 老师 上次您讲了 MD5 算法 用它生成的信息摘要 真的可以被激活成功教程吗 老师 有很多种方法可以激活成功教程 不过需要明确一点 这里所谓的激活成功教程 并非把摘要还原成原文 为什么呢 因为固定 128 位的摘要是有穷的 而原文数量是无穷的 每一个摘要都可以由若干个原文通过 Hash 得到 小明 如果是这样的话 网上所说的 MD5 激活成功教程到底是怎么回事呢 老师 对于 MD5 的激活成功教程 实际上都属于 碰撞 比如原文 A 通过 MD

    2026年3月17日
    2
  • Excel 各种密码的破解,大全建议收藏!

      本文介绍在Excel的多个文件版本中破解各类密码,包含文件的查看、只读密码,工作表、工作簿的保护密码,以及VBA工程密码。内容非常全面,建议你收藏。文件作者加密码是防止数据被查看,修改,所以,文件密码破解仅供于学习参考,请尊重作者版权,不要断人财路。  下面的有些操作不易撤销,为了防止文件被破坏,破解密码前建议备份原文件。1.文件查看、只读密码破解  Excel文件的查看、只…

    2022年4月4日
    2.0K
  • 浅谈可重入函数与不可重入函数

    浅谈可重入函数与不可重入函数在实时系统的设计中 经常会出现多个任务调用同一个函数的情况 如果有一个函数不幸被设计成为这样 那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据 从而导致不可预料的后果 这样的函数是不安全的函数 也叫不可重入函数 相反 肯定有一个安全的函数 这个安全的函数又叫可重入函数 那么什么是可重入函数呢 所谓可重入是指一个可以被多个任务调用的过程 任务在调用时不必担心数据是否会出错 一个可

    2026年3月16日
    3
  • CSDN 发布开源代码托管平台 GitCode

    CSDN 发布开源代码托管平台 GitCode2020 年 9 月 10 日 中国专业 IT 开发者社区 CSDN 正式推出全新升级的开源平台 GitCode 面向国际化市场 具备使用 GitLab 最新高可靠部署方案 独立第三方平台等特点 拥有海量用户基础和品牌加持

    2026年3月20日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号