MySQL使用GROUP BY使用技巧和注意事项总结

 a31da70afc294501ba5d6e07af20bd59.jpeg

⛰️个人主页:     蒾酒

🔥系列专栏:《mysql经验总结》


目录

写在前面

GROUP BY简介

基本用法

单列分组

多列分组

使用聚合函数 

过滤分组结果 

按表达式分组

使用 GROUP BY 的排序 

注意事项

遵循原则

使用能够唯一标识每个分组的字段或字段组合

性能

注意数据类型

写在最后


写在前面

本文介绍了MySQL中GROUP BY的相关介绍

同时欢迎订阅MySQL系列专栏,持续分享MySQL的使用经验。

GROUP BY简介

GROUP BY 子句是 在MySQL 中用于将查询结果按照指定的列或表达式进行分组的关键字。它通常与聚合函数一起使用,能够对每个分组进行统计或计算,并在需要时进行筛选,是处理数据库中大量数据并生成汇总报表的重要工具。

常用的聚合函数有:count() 计数, sum() 求和 , avg() 求平均值, max() 求最大值, min()求最小值。

基本用法

我们拿一张学生表举例

创建表:

CREATE TABLE students (
        student_id INT AUTO_INCREMENT PRIMARY KEY, -- 学生ID,自增主键
        name VARCHAR(50), -- 学生姓名
        major VARCHAR(50), -- 专业
        grade VARCHAR(10), -- 年级
        age INT, -- 年龄
        admission_year datetime -- 入学日期
)

 插入数据:

INSERT INTO students (name, major, grade, age, admission_year) VALUES
('张三', '计算机科学', '大一', 18, '2024-01-01 00:00:00'),
('李四', '数学', '大一', 19, '2024-01-01 00:00:00'),
('王五', '物理', '大二', 20, '2023-01-01 00:00:00'),
('赵六', '化学', '大二', 19, '2023-01-01 00:00:00'),
('小明', '生物', '大三', 21, '2022-01-01 00:00:00'),
('小红', '历史', '大三', 22, '2022-01-01 00:00:00'),
('小李', '地理', '大四', 23, '2021-01-01 00:00:00'),
('小张', '经济学', '大四', 22, '2021-01-01 00:00:00'),
('小王', '文学', '大一', 18, '2024-01-01 00:00:00'),
('小刘', '计算机科学', '大一', 19, '2024-01-01 00:00:00'),
('小杨', '数学', '大二', 20, '2023-01-01 00:00:00'),
('小白', '物理', '大二', 19, '2023-01-01 00:00:00'),
('小黑', '化学', '大三', 21, '2022-01-01 00:00:00'),
('小猫', '生物', '大三', 22, '2022-01-01 00:00:00'),
('小狗', '历史', '大四', 23, '2021-01-01 00:00:00'),
('小鸟', '地理', '大四', 22, '2021-01-01 00:00:00'),
('小鱼', '经济学', '大一', 18, '2024-01-01 00:00:00'),
('小虫', '文学', '大一', 19, '2024-01-01 00:00:00'),
('小兔', '计算机科学', '大二', 20, '2023-01-01 00:00:00'),
('小鸡', '数学', '大二', 19, '2023-01-01 00:00:00'),
('小鸭', '物理', '大三', 21, '2022-01-01 00:00:00'),
('小狐', '化学', '大三', 22, '2022-01-01 00:00:00'),
('小牛', '生物', '大四', 23, '2021-01-01 00:00:00'),
('小马', '历史', '大四', 22, '2021-01-01 00:00:00'),
('小羊', '地理', '大一', 18, '2024-01-01 00:00:00'),
('小猪', '经济学', '大一', 19, '2024-01-01 00:00:00'),
('小狗', '文学', '大二', 20, '2023-01-01 00:00:00'),
('小鸡', '计算机科学', '大二', 19, '2023-01-01 00:00:00'),
('小鸭', '数学', '大三', 21, '2022-01-01 00:00:00'),
('小猫', '物理', '大三', 22, '2022-01-01 00:00:00'),
('小猴', '化学', '大四', 23, '2021-01-01 00:00:00'),
('小狗', '生物', '大四', 22, '2021-01-01 00:00:00'),
('小鸟', '历史', '大一', 18, '2024-01-01 00:00:00'),
('小猫', '地理', '大一', 19, '2024-01-01 00:00:00'),
('小鱼', '经济学', '大二', 20, '2023-01-01 00:00:00'),
('小虫', '文学', '大二', 19, '2023-01-01 00:00:00');

单列分组

例如:按照年级对学生进行分组,并计算每个年级的学生数量。

SELECT grade, COUNT(*)
FROM students
GROUP BY grade;

 

多列分组

例如:按照年级和年龄对学生进行分组,并计算每个年级、年龄组合的学生数量。

SELECT grade, age, COUNT(*)
FROM students
GROUP BY grade, age;

 

使用聚合函数 

例如:计算每个年级的学生平均年龄

SELECT grade, AVG(age)
FROM students
GROUP BY grade;

过滤分组结果 

HAVING 子句在 GROUP BY 之后对分组进行过滤。它允许筛选哪些组将包含在结果中,类似于 WHERE 子句对行进行过滤。通常,HAVING 子句用于过滤聚合后的结果,根据某些条件选择性地包括或排除分组。

例如:筛选出平均年龄超过 20 岁的年级

SELECT grade, AVG(age)
FROM students
GROUP BY grade
HAVING AVG(age) > 20;

 

按表达式分组

例如:按照入学年份(在 "admission_year" 列中)对学生进行分组,并计算每个入学年份的学生数量。

SELECT YEAR(admission_year), COUNT(*)
FROM students
GROUP BY YEAR(admission_year);

使用 GROUP BY 的排序 

例如:按照年级对学生进行分组,并按照每个年级的学生数量从高到低排序。

SELECT grade, COUNT(*)
FROM students
GROUP BY grade
ORDER BY COUNT(*) DESC;

注意事项

遵循原则

确保在SELECT子句中使用的列都包含在GROUP BY子句中,或者是聚合函数的参数。否则,查询可能会产生错误的结果或语法错误。

换句话说group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面

正例:

一共select了grade ,age ,student_id三列,只有student_id列使用了count聚合函数,grade ,age列没用聚合函数就必须跟在group by 后面

SELECT grade, age, COUNT(student_id) as 学生数量
FROM students
GROUP BY grade, age;

 

查询结果返回了年纪跟年龄的所有组合下的学生数量。

反例:

在 SELECT 子句中,除了 COUNT(student_id) 使用了聚合函数外,其余的两列 grade 和 age 都没有使用聚合函数。但是在 GROUP BY 子句中,只列出了 grade 列,而没有包括 age 列。因此,这个查询违反了该原则。

SELECT grade, age, COUNT(student_id) as 学生数量
FROM students
GROUP BY grade;

由于违背了group by的原则,age列没有跟在group by后面导致只查询了不同年级的学生数量统计,然而结果出现的age列仅仅是对应年级下第一个学生的年龄,这样是没有意义的,这样的结果是混乱的。

使用能够唯一标识每个分组的字段或字段组合

正例:

比如专业,年级。

反例:

  1. 唯一标识符字段:如果字段中的值对每个数据行都是唯一的,那么使用这样的字段进行 GROUP BY 将会使每个分组中只有一行数据,且分组数量大。

  2. 包含大量不同值的字段:如果某个字段的取值范围非常广泛,例如一个具有高基数(cardinality)的字段,使用它进行 GROUP BY 可能会导致大量的小分组,从而使结果变得难以理解或者过于细粒度化。

  3. 文本字段:虽然您可以使用文本字段进行 GROUP BY,但是它可能会导致分组的数量庞大,并且对结果的解释会变得更加困难。在这种情况下,最好先对文本字段进行分析或预处理,以便将其转换为更具可分组性的特征。

  4. 包含 NULL 值的字段:如果一个字段大部分值都是 NULL,那么使用它进行 GROUP BY 可能会使得 NULL 值形成一个单独的分组,而其他分组则非常少。

性能

GROUP BY操作可能会导致查询的性能下降,特别是在处理大量数据时。确保索引和适当的优化策略可以帮助提高查询性能。

  1. 创建索引:为 GROUP BY 子句中的字段创建索引,这样数据库可以更快地定位并处理数据。如果您经常使用某个字段进行 GROUP BY,考虑为该字段创建索引以加快查询速度。

  2. 使用覆盖索引:创建覆盖索引以覆盖 GROUP BY 查询中涉及的所有字段。这样可以避免数据库执行额外的查找操作,从而提高性能。

  3. 限制结果集:在 GROUP BY 子句之前使用 WHERE 子句过滤数据,以减少处理的数据量。只选择必要的数据行可以显著提高查询性能。

  4. 使用聚合函数:考虑使用聚合函数(如SUM、COUNT、AVG等)来减少数据量。尽量在 GROUP BY 之前使用聚合函数,以便减少处理的数据量。

  5. 避免使用复杂表达式:在 GROUP BY 子句中尽量避免使用复杂的表达式或函数。这些表达式可能会增加处理时间,并使索引失效。

注意数据类型

在MySQL中,虽然可以在几乎任何数据类型的列上使用GROUP BY子句,但某些数据类型可能在实际应用中带来挑战或性能问题。

适合分组的数据类型

  • INT、BIGINT等整数类型:这些类型在进行分组和比较时比较可靠。
  • VARCHAR、CHAR等字符类型:字符类型在比较和分组时更具可预测性。

不适合分组的数据类型

  • BLOB和TEXT:用于存储大型文本或二进制数据,比较和分组时性能较差。

  • JSON:嵌套结构复杂,直接比较不可靠,导致分组性能问题。

  • GEOMETRY:用于存储空间数据,比较复杂且计算量大,难以进行分组。

  • VARBINARY/BINARY:存储二进制数据,可能导致非字符内容的比较问题。

  • FLOAT和DOUBLE:由于浮点数精度问题,分组结果可能不稳定。

总的来说,适合在 GROUP BY 中使用的数据类型通常是具有明确顺序或可数性质的数据类型,而不是基于文本或二进制的数据类型。

写在最后

MySQL使用GROUP BY使用技巧和注意事项总结到这里就结束了,欢迎评论区补充,指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/595375.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PCB 阻抗设置

凡亿电路有详细的阻抗设计 https://baijiahao.baidu.com/s?id1773006310888936808&wfrspider&forpc 差分基本上是100ohm, 单端是50ohm 布线阻抗通常是, -设置叠层关系 层的定义设计原则: 1)主芯片相临层为地平面,提供器…

Whisper、Voice Engine推出后,训练语音大模型的高质量数据去哪里找?

近期,OpenAI 在语音领域又带给我们惊喜,通过文本输入以及一段 15 秒的音频示例,可以生成既自然又与原声极为接近的语音。值得注意的是,即使是小模型,只需一个 15 秒的样本,也能创造出富有情感且逼真的声音。…

图像处理-图像平滑

图像平滑 前言一、概念介绍1.1 图像的平滑1.2 图像中噪声的分类1.3 MATLAB的添加噪音代码 二、空间域平滑滤波2.1 均值滤波2.2 原理计算 总结 前言 在图像的获取、传输和存储过程常常收到各种噪声的干扰和影响,使得图像的质量下降,为了获得高质量的数字…

CPU炼丹——YOLOv5s

1.Anaconda安装与配置 1.1安装与配置 Anaconda3的安装看下面的教程: 最新Anaconda3的安装配置及使用教程(详细过程)http://t.csdnimg.cn/yygXD,接上面文章下载后,配置环境变量的时候记得在原来你装的Python更下面添…

如何快速找出文件夹里的全部带有英文纯英文的文件

参考此文章:如何快速找出文件夹里的全部带有中文&纯中文的文件 只需要根据自己的需求,把下面相关的设置调整好即可

【Hadoop】MapReduce (六)

MapReduce 组件 输入格式 - InputFormat InputFormat发生在Mapper之前,用于对数据进行切分和读取,会将读取到的数据传递给MapTask处理。所以InputFormat读取到的数据是什么格式,Mapper接收到的数据就是什么格式 作用 getSplits&#xff1a…

YOLO系列改进,自研模块助力涨点

目录 一、原理 二、代码 三、添加到YOLOv5中 一、原理 论文地址:

“先锋”西凤

执笔 | 文 清 编辑 | 古利特 制曲是酿酒的第一道工序,也是中国酿酒史上的一大创新,对白酒风味的影响至关重要。西凤酿酒人坚信“曲是酒之骨”,“曲”的品质决定酒的“骨气”,“酒曲”是酒体形成主题风味的基本定型元素和催化剂…

OpenNJet如何做到让用户永远在线

前言 最近看到了国内开源的一个名为OpenNJet的项目,有一个响亮的口号:“下一代云原生应用引擎”。 一下子就被吸引到了。 先看下官方对OpenNJet的介绍: OpenNJet 应用引擎是基于 NGINX 的面向互联网和云原生应用提供的运行时组态服务程序&…

如何根据配置动态生成Spring的Bean?

一、问题解析 在 Spring 应用中,根据运行时的配置(比如数据库配置、配置文件、配置中心等)动态生成 Spring Bean 是一种常见需求,特别是在面对多环境配置或者需要根据不同条件创建不同实例时。 Spring 提供了几种方式来实现这一需…

spice common模块

库分为三部分libspice-common.a,libspice-common-client.a,libspice-common-server.a。 1、libspice-common.a工程编译代码 # # libspice-common # spice_common_sources [ agent.c, agent.h, backtrace.c, backtrace.h, canvas_utils.c, canvas_utils.h, demarsha…

sql编写规范(word原件)

编写本文档的目的是保证在开发过程中产出高效、格式统一、易阅读、易维护的SQL代码。 1 编写目的 2 SQL书写规范 3 SQL编写原则 软件全套资料获取进主页或者本文末个人名片直接获取。

高德地图在vue3项目中使用:实现画矢量图、编辑矢量图

使用高德地图实现画多边形、矩形、圆&#xff0c;并进行编辑保存和回显。 1、准备工作 参考高德地图官网&#xff0c;进行项目key申请&#xff0c;链接: 准备 2、项目安装依赖 npm i amap/amap-jsapi-loader --save3、地图容器 html <template><!-- 绘制地图区域…

GNSS 地球自转改正算例分析

文章目录 Part.I IntroductionPart.II 由地球自转引起的误差的概念和改正方法Chap.I 误差概念Chap.II 改正方法 Part.II 算例分析Chap.I 基础数据Chap.II 计算过程 AppendixReference Part.I Introduction 为了更好地理解 地球自转改正&#xff0c;本文将介绍一个算例。 Part.…

手动交互式选点提取三维点云轮廓边界线 附python代码

一种新的三维点云轮廓边界提取方案: 1 手动选择一个边界或者其附近的点 2 自动搜索临近区域,并找到附近的平面和进行平面分割 3 提取平面的交点 4 该交点就是点云的轮廓边界点,把它往两边延展,就是完整的点云轮廓边界 import open3d as o3d import numpy as np import …

Java模块化系统:引领代码革命与性能飞跃

JDK工程结构的问题 在说Java模块化系统之前&#xff0c;先来说说Java9之前的JDK在工程结构上的问题&#xff0c;从JDK本身的问题说起&#xff0c;Java从1996年发布第一版到2017年发布Java9&#xff0c;中间经历了近20年的时间&#xff0c;在这期间发布了无数个大大小小的版本用…

RESTFul风格设计和实战

四、RESTFul风格设计和实战 4.1 RESTFul风格概述 4.1.1 RESTFul风格简介 RESTful&#xff08;Representational State Transfer&#xff09;是一种软件架构风格&#xff0c;用于设计网络应用程序和服务之间的通信。它是一种基于标准 HTTP 方法的简单和轻量级的通信协议&#x…

YAML如何操作Kubernetes核心对象

Pod Kubernetes 最核心对象Pod Pod 是对容器的“打包”&#xff0c;里面的容器&#xff08;多个容器&#xff09;是一个整体&#xff0c;总是能够一起调度、一起运行&#xff0c;绝不会出现分离的情况&#xff0c;而且 Pod 属于 Kubernetes&#xff0c;可以在不触碰下层容器的…

存储或读取时转换JSON数据

一、 数据库类型 二、使用Hutool工具 存储时将数据转换为JSON数据 获取时将JSON数据转换为对象 发现问题&#xff1a; 原本数据对象是Address 和 Firend但是转换完成后数据变成了JSONArray和JSONObject 三、自定义TypeHandler继承Mybatis的BaseTypeHandler处理器 package …

Feign 和 OpenFeign 的区别

Feign 和 OpenFeign 都是用来进行服务间调用的客户端库&#xff0c;它们旨在简化HTTP API客户端的编写过程&#xff0c;使得编写对外部服务的接口就像调用本地方法一样简单。尽管它们有相似之处&#xff0c;但也存在一些关键差异&#xff1a; 归属和演进&#xff1a; Feign 最初…