MySQL学习之分组查询的用法详解

目录
  • 为什么要分组
  • 逐级分组
    • 逐级分组对 SELECT 子句的要求
    • 对分组结果集再次做汇总计算
  • GROUP_CONCAT 函数
  • GROUP BY 子句的执行顺序

该章节来开始学习分组查询,上一章节我们学习了聚合函数,默认统计的是全表范围内的数据,配合上 WHERE 就能够缩小统计的范围了。但是这并不能满足我们的要求,比如说我们按照之前的数据表查询每个部门的平均底薪是多少?这样的记录就需要针对部门编号进行分组了。根据分组的情况统计分组内的最大值、最小值、平均值等等。如此就能够满足刚刚提到的 “查询每个部门的平均底薪” 这样的需求了,另外,“分组查询” 是 SQL 中很重要的一个语法,大家一定要好好掌握它。

为什么要分组

上面也提到,聚合函数默认是对全表范围内的数据做统计,在一些特定的场景下不太适用,就比如 对数据分别进行统计的 场景。

由于聚合函数的这样的局限性,也就产生了分组的概念,于是就有了分组的语法。

分组的语法是通过 “GROUP BY” 来实现的。

"GROUP BY" 子句的作用是通过一定的规则将一个数据集划分成若干个小的区域,然后再针对每个小区域分别进行数据汇总处理

分组语句演示案例:(计算每一个部门的平均底薪)

SELECT deptno, AVG(sal)
FROM t_emp
GROUP BY deptno;

-- 利用 GROUP BY 子句将 deptno 进行分组,在利用 AVG() 聚合函数计算各个 deptno(部门) 的平均月薪

这里的小数,可能看着不太舒服,我们可以使用 ROUND() 函数将 平均工资四舍五入变成整数。

SELECT deptno, ROUND(AVG(sal))
FROM t_emp
GROUP BY deptno;

逐级分组

有的时候仅有大的分组还不够,还需要在大的分组里面划分出晓得分组,然后再执行统计计算,于是就有了逐级分组。

什么是逐级分组? MySQL 数据库支持多列分组条件,执行的时候按照多列去依次执行,这就是逐级分组。

示例如下:(查询每个部门里,每种职位的人员数量和平均工资。)

SELECT deptno, job, COUNT(*), AVG(sal)
FROM t_emp
GROUP BY deptno, job
ORDER BY deptno;

-- 首先要按照部门对员工进行分组,在部门里,还要按照职务去分组; 就是 "GROUP BY deptno, job"
-- 然后再用 聚合函数的 AVG 计算平均的月薪; 就是 "SELECT deptno, job, COUNT(*), AVG(sal)"
-- 最后按照 deptno(部门编号) 排序,使用 ORDER BY 进行升序排序。

逐级分组对 SELECT 子句的要求

查询语句中如果包含有 “GROUP BY” 子句,那么 “SELECT” 子句中的内容就必须要遵守以下规定
"SELECT" 子句中可以包含聚合函数,或者 "GROUP BY" 子句的分组列,其余内容均不可以出现在 "SELECT" 子句中
SQL 示例如下:(遵守规定示例)

SELECT deptno, COUNT(*), AVG(sal)
FROM t_emp
GROUP BY deptno;

SQL 示例如下:(不遵守规定示例)

SELECT deptno, COUNT(*), AVG(sal), sal
FROM t_emp
GROUP BY deptno;

-- 这条语句是无法执行成功的,因为在 "SELECT" 子句中,有一个 "sal" 的字段
-- 这个 "sal" 字段 没有在 GROUP BY 中去分组,本身也没有聚合函数,就是一个普通的字段

-- 造成无法执行、报错的原因是因为,"SELECT deptno, COUNT(*), AVG(sal), sal"
-- 中的 "deptno、COUNT(*)、AVG(sal)" 返回的是 "GROUP BY" 一个结果集分组的同级信息;
-- 而 "sal" 字段又是多条匹配记录,前后肯定是匹配不上的,所以这个 SQL 语句是无法执行成功的。

-- 同时因为标准的 SQL 规定,对表进行聚合查询的时候,只能在 SELECT 子句中写下面 3 种内容:
-- 通过 GROUP BY 子句指定的聚合键、聚合函数(SUM 、AVG 等)、常量。
-- 所以在使用 SQL 语句记性数据表查询时,一定要严格遵守 SQL 的语法规定。

对分组结果集再次做汇总计算

来看一个示例:(查询 员工表中各个部门的人数,各个部门的平均月薪、最大月薪、最小月薪、按照员工号进行排序,并针对各个部门再次做一个汇总统计。)

SELECT deptno, COUNT(*), AVG(sal), MAX(sal), MIN(sal)
FROM t_emp
GROUP BY deptno
WITH ROLLUP;

-- 这里的 "WITH ROLLUP" 子句就是针对 "deptno"分组的结果集,再一次的进行汇总计算

PS:该 SQL 语句主要是为了体现 "WITH ROLLUP" 关键字的效果,是对聚合函数的再次执行汇总计算。

GROUP_CONCAT 函数

上文中的 "逐级分组对 SELECT 子句的要求" 部分的时候解释了为什么会有这样的要求,就是聚合函数返回一条记录的结果与非分组字段的多条记录的结果无法匹配。

如果想要想要匹配,那就要把非分组的字段的多条记录转换成一条记录,MySQL 提供的 GROUP_CONCAT 函数就可以将分组查询中的非分组字段中的多条记录合并成一条记录。

SQL 语句 "GROUP_CONCAT" 示例如下:(查询每个部门内底薪超过 2000元的人数和员工姓名,这里的员工姓名就是非分组的字段)

SELECT deptno, GROUP_CONCAT(ename), AVG(sal),COUNT(*)
FROM t_emp
WHERE sal >= 2000
GROUP BY deptno;

-- 查询员工表,筛选条件为月薪大于等于 2000 ,以 "deptno" 为分组
-- "ename" 字段没有分组,但是我们使用 "GROUP_CONCAT" 函数将 "ename" 的多条返回记录转换为一条记录

GROUP BY 子句的执行顺序

截止到目前为止,我们所学习的所有子句,执行顺序如下:

FROM ---> WHERE ---> GROUP BY ---> SELECT ---> ORDER BY ---> LIMIT

到此这篇关于MySQL学习之分组查询的用法详解的文章就介绍到这了,更多相关MySQL分组查询内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL 分组查询和聚合函数

    概述 相信我们经常会遇到这样的场景:想要了解双十一天猫购买化妆品的人员中平均消费额度是多少(这可能有利于对商品价格区间的定位):或者不同年龄段的化妆品消费占比是多少(这可能有助于对商品备货量的预估). 这个时候就要用到分组查询,分组查询的目的是为了把数据分成多个逻辑组(购买化妆品的人员是一个组,不同年龄段购买化妆品的人员也是组),并对每个组进行聚合计算的过程:. 分组查询的语法格式如下: select cname, group_fun,... from tname [where conditio

  • MySQL连表查询分组去重的实现示例

    目录 业务逻辑 数据表结构 查询逻辑 SQL脚本 脚本说明 业务逻辑 通过多种渠道将小程序的活动页链接发布出去,比如通过多多种短信附带链接( channel 就记为 sms1,sms2,sms3 ),或者海报上面贴微信小程序的二维码( channel 记为 qrcode1,qrcode2,qrcode3 ),线下会员通过扫描二维码也能进入小程序指定的活动页,亦或者是通过其他会员分享的小程序链接也可以进入小程序( channel 记为 share).这些不同的进入方式在我这篇文章统称为不同的渠道,

  • MySQL 子查询和分组查询

    概述 子查询是SQL查询中的重要一块,是我们基于多表之间进行数据聚合和判断的一种手段,使得我们的处理复杂数据更加的便捷,这一节我们主要来了解一下子查询. 先做一下数据准备,这边建立三张表:班级.学生.毕业成绩表,用于后面的操作: drop database if exists `Helenlyn_Class`; create database `Helenlyn_Class`; /*班级表*/ DROP TABLE IF EXISTS `classes`; CREATE TABLE `class

  • mysql按照时间分组查询的语句

    mysql 按年.月.周.日分组查询 1.按照年份分组查询 SELECT DATE_FORMAT(t.bill_time,'%Y') month_time,sum(t.pay_price) total FROM f_bill t GROUP BY month_time; 查询结果 2.按照月份分组查询 SELECT DATE_FORMAT(t.bill_time,'%Y-%m') month_time,sum(t.pay_price) total FROM f_bill t GROUP BY m

  • 详解MySQL中的分组查询与连接查询语句

    分组查询 group by group by 属性名 [having 条件表达式][ with rollup] "属性名 "指按照该字段值进行分组:"having 条件表达式 "用来限制分组后的显示,满足条件的结果将被显示:with rollup 将会在所有记录的最后加上一条记录,该记录是上面所有记录的总和. 1)单独使用 group by 单独使用,查询结果只显示一个分组的一条记录. 实例: select * from employee group by sex;

  • MySQL 分组查询的优化方法

    MySQL 在处理 GROUP BY 和 DISTINCT 查询的方式在大多数情况下类似,事实上,在优化过程中有时候会把在这两种方式中转换.两类查询都能够从索引中受益,通常,这也是优化这两种查询最为重要的方式. 在无法使用索引时,MySQL 对于 GROUP BY 查询有两种策略:使用临时表或者 filesort 执行分组.对于给定的查询,两种方式都没法更高效.我们可以通过配置 SQL_BIG_RESULT 和 SQL_SMALL_RESULT 来指定优化器选择其中一个方式. 通常,对查询表的i

  • MySQL学习之分组查询的用法详解

    目录 为什么要分组 逐级分组 逐级分组对 SELECT 子句的要求 对分组结果集再次做汇总计算 GROUP_CONCAT 函数 GROUP BY 子句的执行顺序 该章节来开始学习分组查询,上一章节我们学习了聚合函数,默认统计的是全表范围内的数据,配合上 WHERE 就能够缩小统计的范围了.但是这并不能满足我们的要求,比如说我们按照之前的数据表查询每个部门的平均底薪是多少?这样的记录就需要针对部门编号进行分组了.根据分组的情况统计分组内的最大值.最小值.平均值等等.如此就能够满足刚刚提到的 “查询

  • MySQL学习之日期函数的用法详解

    目录 获取 系统时间 函数 日期格式化 函数 日期函数练习① 日期函数练习② 日期计算的注意事项 日期偏移计算 计算日期之间相隔的天数 获取 系统时间 函数 “NOW()” 函数 能够获得当前系统日期和时间,格式如下:“YYYY-MM-DD hh:mm:ss” (这里的小时单位是 24 小时制) “CURDATE()” 函数 能够获取到当前系统的日期,格式如下:“YYYY-MM-DD” “CURTIME()” 函数 能够获得当前系统时间,格式如下:“hh:mm:ss” (24小时制) SELEC

  • mysql之group by和having用法详解

    GROUP BY语法可以根据给定数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表. select子句中的列名必须为分组列或列函数,列函数对于group by子句定义的每个组返回一个结果. 某个员工信息表结构和数据如下: id name dept salary edlevel hiredate 1 张三 开发部 2000 3 2009-10-11 2 李四 开发部 2500 3 2009-10-01 3 王五 设计部 2600 5 2010-10-02 4 王六 设计部 2300 4

  • Go语言学习之context包的用法详解

    目录 前言 需求一 需求二 Context 接口 emptyCtx valueCtx 类型定义 WithValue cancelCtx 类型定义 cancelCtx WithCancel timerCtx 类型定义 WithDeadline WithTimeout 总结 前言 日常 Go 开发中,Context 包是用的最多的一个了,几乎所有函数的第一个参数都是 ctx,那么我们为什么要传递 Context 呢,Context 又有哪些用法,底层实现是如何呢?相信你也一定会有探索的欲望,那么就跟

  • Yii2中hasOne、hasMany及多对多关联查询的用法详解

    前言 hasOne.hasMany是Yii2特有的用于多表关联查询的函数,平时在使用多表关联查询的时候建议使用它们.为什么?因为这种方式关联查询出来的结果会保留Yii2自有的表头排序功能,以及CheckboxColumn中input的id存值,至于还有没有其它的好处就需要大家去挖掘了,笔者目前就发现了这两个常用的好处.其他的关联查询,像yiidbQuery查询或者原生的SQL语句查询都没有,查询出来在列表展示的时候,表头一排黑. Yii2的hasOne.hasMany多表关联查询,不管是文档还是

  • C#学习笔记- 随机函数Random()的用法详解

    Random.Next() 返回非负随机数: Random.Next(Int) 返回一个小于所指定最大值的非负随机数 Random.Next(Int,Int) 返回一个指定范围内的随机数,例如(-100,0)返回负数 1.random(number)函数介绍 见帮助文档,简单再提一下,random(number)返回一个0~number-1之间的随机整数.参数number代表一个整数. 示例: trace(random(5)); 2.Math.random() 见帮助文档.返回一个有14位精度的

  • MySQL学习之数据库表五大约束详解小白篇

    目录 1.约束概念和分类 2.五大约束的添加和删除 2.1添加约束的六种方法 2.2三种删除约束的方式 2.3五大约束分别对应的添加删除方式(序号对应2.1和2.2) 2.4对于创建约束的总结 2.5对于主键和唯一的区别 3.自增长列 3.1概念 3.2在创建表的时候添加主键约束,并且完成主键自增长的例子 3.3自增长的添加和删除 3.4设置自增长步长 1.约束概念和分类 1.1约束的概念: 对表中的数据进行限定,保证数据的正确性,有效性,完整性 1.2约束分类 1.主键约束(primary k

  • Go语言学习之映射(map)的用法详解

    目录 1. 什么是 map 2. 创建 map 3. 访问 map 4. nil map和空map 5. map中元素的返回值 6. len()和delete() 7. 测试map中元素是否存在 8. 迭代遍历 map 9. 获取map中所有的key 10. 传递map给函数 1. 什么是 map Map 是一种无序的键值对的集合.Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值 Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash

  • Golang学习之反射机制的用法详解

    目录 介绍 TypeOf() ValueOf() 获取接口变量信息 事先知道原有类型的时候 事先不知道原有类型的时候 介绍 反射的本质就是在程序运行的时候,获取对象的类型信息和内存结构,反射是把双刃剑,功能强大但可读性差,反射代码无法在编译阶段静态发现错误,反射的代码常常比正常代码效率低1~2个数量级,如果在关键位置使用反射会直接导致代码效率问题,所以,如非必要,不建议使用. 静态类型是指在编译的时候就能确定的类型(常见的变量声明类型都是静态类型):动态类型是指在运行的时候才能确定的类型(比如接

  • C++学习之Lambda表达式的用法详解

    目录 简介 捕获 原理 Lambda回调 简介 Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数.Lambda表达式可以表示闭包(注意和数学传统意义上的不同). 闭包就是能够读取其他函数内部变量的函数,可以理解成“定义在一个函数内部的函数“.在本质上,闭包是将函数内部和函数外部连接起来的桥梁. C++中的Lambda表达式

随机推荐