当前位置: 首页 > news >正文

MySQL分组查询GROUP BY

GROUP BY子句

select中使用GROUP BY子句可以对指定列进行分组查询。

**需要满足:**使用GROUP BY进行分组查询时,SELECT指定的字段必须是“分组依据字段”(要对哪个列进行分组),其他没有指定分组字段若想要出现在SELECT中则必须包含在聚合函数中。

在这里插入图片描述

示例:

-- 创建示例用表
drop table if exists emp;
create table emp (id bigint primary key auto_increment,name varchar(20) not null comment '员工姓名';role varchar(20) not null comment '职位';salery decimal(10,2) not null comment '工资';
)-- 计算不通角色工资的平均值
select role,avg(salary) from emp group by role;-- 使用ROUND(数值,小数点位数)
select role,round(avg(salary),2) as 平均工资 from emp group by role;-- group by 子句后面可以跟order by子句
select role,round(avg(salary),2) as 平均工资 from emp group by role order by 平均工资 ASC;

ROUND()

是一个常用的数值函数,核心作用是将指定数值按需求四舍五入到指定的小数位数,也可用于对整数位进行四舍五入(如四舍五入到十位、百位)。

语法

ROUND(数值表达式, 小数位数)
  • 数值表达式:必填,需要进行四舍五入的数值(可以是直接的数字、字段名、或其他数值计算结果,如 score * 0.8)。

  • 小数位数

    :可选,整数类型,用于指定四舍五入后的小数保留位数:

    • 当值为 正数 时:保留指定的小数位(如 2 表示保留 2 位小数)。
    • 当值为 负数 时:对整数部分进行四舍五入(如 -1 表示四舍五入到十位,-2 表示四舍五入到百位)。
    • 当值为 0 或省略 时:默认四舍五入到整数(保留 0 位小数)。

HAVING

GROUP BY子句分组后,需要对分组结果再进行条件过滤时,不能使用WHERE语句,而需要使用HAVING

where是对表中每一行的真实数据进行过滤的,having是对ground by之后,通过聚合函数计算出来的结果进行过滤的

示例:

select role,avg(salary) from emp group  by role having avg(salary) > 10000 and avg(salary) < 20000

where用在from表名之后,也就是分组之前,而HAVING跟在group by 子句之后

-- 查询每个职位的最高工资、最低工资、平均工资
select role,max(salary),min(salary),avg(salary) from emp group by role;-- 显示平均工资低于1500的职位并他的平均工资
-- 1.按职位分组 2.使用相应的聚合函数 3.使用having子句对分组的结果进行过滤
select role,avg(salary) from emp group by role having avg(salary)<1500;

在SQL中关键的语句的执行顺序:

FROM/WHEREGROUP BY聚合计算(如 AVG(salary))HAVINGSELECT(含别名定义)

别名的定义在having和where之后,所以在这两个关键字的子句中不能使用别名。

标准SQL中不允许在GROUP BY中直接使用SELECT别名,但是在MySQL允许在GROUP BY中使用SELECT别名,这是MySQL的扩展功能。

当使用多个字段进行 GROUP BY

比如:

GROUP BY student.id, student.name;

结果集会按照指定的多个字段的组合进行分组,也就是说:

  • 数据库会先按照第一个字段(student.id)分组
  • 如果第一个字段的值相同,再按照第二个字段(student.name)进一步分组
  • 最终,只有当这两个字段的值完全相同时,才会被分到同一个组里

举例说明

假设有表 student

idnamescore
1张三80
1张三85
1李四90
2王五75
2王五78

执行:

SELECT id, name, COUNT(*) AS cnt
FROM student
GROUP BY id, name;

结果:

idnamecnt
1张三2
1李四1
2王五2

解释

  • id=1, name=张三 出现了 2 次 → 分到同一组
  • id=1, name=李四 只出现了 1 次 → 分到另一组
  • id=2, name=王五 出现了 2 次 → 分到同一组

特点

  1. 分组顺序重要:先按第一个字段分,再按第二个字段细分
  2. 组的唯一性:多个字段组合值唯一才能成为一个组
  3. 结果集行数:等于不同组合值的数量

SQL 标准中的规定

SQL 标准规定:

当使用 GROUP BY 时,SELECT 列表中的列必须满足以下条件之一:

  1. 出现在 GROUP BY 子句中
  2. 被包含在聚合函数中(如 SUMCOUNTMAX 等)

原因

GROUP BY 会将多行数据聚合成一行(每个分组一行)。如果某个列既没有分组,也没有聚合,那么它在分组内可能有多个不同的值,数据库不知道该返回哪一个,因此会报错。

为什么有些情况下可以省略

虽然 SQL 标准要求严格,但某些数据库(例如 MySQL 默认配置下)允许非聚合、非分组的列出现在 SELECT 列表中,这被称为 ONLY_FULL_GROUP_BY 模式关闭

当你在 MySQL 中关闭 ONLY_FULL_GROUP_BY 时:

  • 如果分组内的该列值全部相同,MySQL 会随便返回该分组的一个值(实际上是第一个遇到的值)。
  • 如果分组内的值不相同,MySQL 会任意取一个值返回,这可能导致不可预期的结果。

例如:

SELECT student.id, student.name
FROM student
GROUP BY student.id;

这里 student.name 没在 GROUP BY 里,也没有聚合,但:

  • 如果一个 id 只对应一个 name(主键与唯一约束),那么每个分组内的 name 一定相同,返回的值是确定的。
  • 如果一个 id 对应多个不同的 name(数据异常),那么返回的 name 就是随机的。

满足SQL标准的写法

为了代码的可移植性和结果的确定性,建议:

  • 如果要显示该列,就把它加入 GROUP BY

例如:

-- 方法:加入 GROUP BY
SELECT student.id, student.name
FROM student
GROUP BY student.id, student.name;
http://www.dtcms.com/a/516633.html

相关文章:

  • 数组——双指针:75.颜色分类
  • LLD文档核心:从模块设计到落地开发
  • 雄安做网站深圳出台科技支持政策
  • 网站域名能更该吗怎样用模板建网站
  • proc文件系统入门到精通教程
  • 点积、内积与哈达玛积详解
  • 杭州模板建站2022注册公司取名
  • 政务网站建设论文西地那非片吃了多久会硬起来
  • 金融杠杆全解析:从铁矿期货保证金计算到期权盈亏分析
  • 【工具变量】绿色金融改革创新试验区DID数据集(2000-2024年)
  • Prometheus:从概述到部署
  • 32.768khz音叉式圆柱型贴片晶振CMR200T
  • ROS2创建Python与C++功能包指南以及什么是节点(ros2第一章)
  • wordpress可以建网站吗电子商务网站建设 教案
  • vr中xr射线长度调整
  • 怎样做微信挂机平台网站建设公司的网站首页
  • 【Go】P11 掌握 Go 语言函数(二):进阶玩转高阶函数、闭包与 Defer/Panic/Recover
  • 无奈!我用go写了个MySQL服务
  • 重庆网站建设业务招聘网站推广方式主要通过
  • GaussDB 数据集成方案:ETL 工具如何简化企业上云过程
  • 如何解决 pip install 安装报错 externally-managed-environment(PEP 668)问题
  • 相向双指针|两数之和II-输入有序数组|三数之和|统计和小于目标的下标对数目|最接近的三数之和|四数之和|有效三角形的个数
  • ffmpeg4.4.2 gcc 15.2.0 编译错误
  • 免费的大语言模型API接口
  • css3 学习笔记
  • 高水平的网站建设南昌做个网站多少钱
  • 宁夏建设工程质量安全监督总网站wordpress发送文章链接过期
  • Vscode 如何配置远程环境的 ssh 连接
  • 昆明参差网站开公司建网站
  • 专业点的网站制作公司建设一个公司网站需要什么条件