MySQL | GROUP BY子句使用详解

关注:CodingTechWork

引言

  在 MySQL 中,GROUP BY 子句用于将查询结果按照一个或多个列进行分组。每个分组会返回一行,通常与聚合函数(如 COUNT(), SUM(), AVG() 等)一起使用,用于汇总每个分组的数据。
  
本篇博客将深入探讨 MySQL 中 GROUP BY 的原理、常见的使用场景,并通过多个场景提供详细的代码示例,帮助大家全面理解 GROUP BY的使用。

GROUP BY 原理

  GROUP BY的核心作用是将查询结果中的数据按照指定的列进行分组。每个分组会包含原表中的一条记录,该记录代表了该组的数据。
  在 SQL 查询中,GROUP BY 通常与聚合函数配合使用,进行数据统计和汇总。聚合函数会对每个分组中的数据进行操作,返回每个分组的聚合结果。例如,使用COUNT()可以计算每个分组的行数,使用SUM()可以计算每个分组的值的和。

SELECT column_name, aggregate_function(column_name)
FROM table_name
GROUP BY column_name;

GROUP BY 语法结构

SELECT column1, aggregate_function(column2)
FROM table_name
WHERE condition
GROUP BY column1
HAVING condition;
  • column1: 用于分组的列。
  • aggregate_function(column2): 聚合函数,通常是COUNT(), SUM(), AVG(), MIN(), MAX()等。
  • WHERE: 用于过滤数据,分组前应用。
  • HAVING: 用于对分组后的数据进行过滤,通常与聚合函数一起使用。

GROUP BY 使用场景

数据汇总与统计

GROUP BY最常见的应用场景是对数据进行汇总和统计,通常与聚合函数结合使用。

分组统计

通过对某些字段进行分组,获得每个组的汇总统计。

筛选特定条件的分组

结合HAVING子句,可以筛选符合条件的分组。与 WHERE子句不同,WHERE作用于行数据,HAVING作用于分组后的数据。

场景代码示例

基本的 GROUP BY 示例

假设有一个orders表,结构如下:

CREATE TABLE orders (order_id INT AUTO_INCREMENT PRIMARY KEY,customer_id INT,order_date DATE,total_amount DECIMAL(10, 2)
);

插入数据:

INSERT INTO orders (order_id, customer_id, order_date, total_amount) VALUES
(1, 101, '2025-01-10', 250.00),
(2, 102, '2025-01-10', 150.00),
(3, 101, '2025-01-11', 300.00),
(4, 103, '2025-01-11', 400.00),
(5, 101, '2025-01-12', 200.00),
(6, 102, '2025-01-12', 350.00),
(7, 104, '2025-01-13', 500.00),
(8, 101, '2025-01-13', 450.00),
(9, 103, '2025-01-13', 600.00);

查询每个customer_id的订单数量

sql

SELECT customer_id, COUNT(*) AS order_count
FROM orders
GROUP BY customer_id;

解释

通过GROUP BY customer_id,每个customer_id会成为一个组,COUNT(*) 会计算每个 customer_id 的订单数量。

结果

customer_idorder_count
1014
1022
1032
1041
  • 客户 101 有 4 个订单。
  • 客户 102 有 2 个订单。
  • 客户 103 有 2 个订单。
  • 客户 104 有 1 个订单。

使用 SUM() 聚合函数计算每个客户的总消费

sql

SELECT customer_id, SUM(total_amount) AS total_sales
FROM orders
GROUP BY customer_id;

解释

通过 SUM(total_amount) 聚合函数,查询每个 customer_id的总消费金额。

结果

customer_idtotal_sales
1011700.00
102500.00
1031000.00
104500.00
  • 客户 101 总销售额为 1700.00。
  • 客户 102 总销售额为 500.00。
  • 客户 103 总销售额为 1000.00。
  • 客户 104 总销售额为 500.00。

使用 HAVING 子句筛选特定条件的分组

假设我们想找出总消费大于 1000 的客户:

sql

SELECT customer_id, SUM(total_amount) AS total_spent
FROM orders
GROUP BY customer_id
HAVING total_spent > 1000;

解释

HAVING子句用于筛选分组后的数据。在这个例子中,只有那些消费总额大于 1000 的客户才会被返回。

结果

customer_idtotal_sales
1011700.00

多列分组

我们可以根据多个列进行分组,假设我们想根据customer_idorder_date统计每天每个客户的消费总额:

sql

SELECT customer_id, order_date, SUM(total_amount) AS total_spent
FROM orders
GROUP BY customer_id, order_date;

解释

通过GROUP BY customer_id, order_date,查询结果将返回每个客户每天的消费总额。

结果

customer_idorder_dateorder_count
1012025-01-101
1012025-01-111
1012025-01-121
1012025-01-131
1022025-01-101
1022025-01-121
1032025-01-111
1032025-01-131
1042025-01-131
  • 每个客户在每个日期的订单数被列出。

使用 GROUP BY 和 JOIN

customers表

假设customers如下

CREATE TABLE customers (customer_id INT,customer_name VARCHAR(100),region VARCHAR(50)
);

插入数据

INSERT INTO customers (customer_id, customer_name, region) VALUES
(101, 'Alice', 'North'),
(102, 'Bob', 'South'),
(103, 'Charlie', 'East'),
(104, 'David', 'South');

sql

我们可以使用 JOIN 将它们连接,并根据客户的地区(region)进行分组,统计每个地区的客户订单数量:

SELECT c.region, COUNT(o.order_id) AS order_count
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
GROUP BY c.region;

解释

我们通过 JOINorders 表和 customers 表连接,基于 customer_id 这一共同列。然后,我们根据 region 对客户所在地区进行分组,统计每个地区的订单数量。

结果

regionorder_count
North3
South3
East2

GROUP BY 和日期分组

sales 表

假设我们有一个 sales 表,记录了每日的销售数据:

CREATE TABLE sales (order_id INT,order_date DATE,sales_amount DECIMAL(10, 2)
);

插入数据

INSERT INTO sales (order_id, order_date, sales_amount) VALUES
(1, '2025-01-10', 250.00),
(2, '2025-01-11', 150.00),
(3, '2025-02-05', 300.00),
(4, '2025-02-15', 200.00),
(5, '2025-02-20', 400.00);

查询sql

SELECT YEAR(order_date) AS year, MONTH(order_date) AS month, SUM(sales_amount) AS total_sales
FROM sales
GROUP BY YEAR(order_date), MONTH(order_date);

解释

通过 YEAR(order_date) 和 MONTH(order_date),我们可以按年份和月份进行分组,查询每个月的总销售额。

结果

yearmonthtotal_sales
20251400.00
20252900.00

使用 GROUP BY 和 ORDER BY

在某些情况下,可能希望按某些列对分组结果进行排序。例如,按总消费额从高到低排序客户:

查询sql

SELECT customer_id, SUM(total_amount) AS total_spent
FROM orders
GROUP BY customer_id
ORDER BY total_spent DESC;

解释

我们查询每个客户的总消费金额,并按照 total_spent降序排列客户,显示最消费最多的客户。

结果

customer_idtotal_spent
1011200.00
1031000.00
102500.00
104500.00

注意事项与最佳实践

  • **聚合函数与 GROUP BY 一起使用GROUP BY通常与聚合函数一起使用。没有聚合函数的GROUP BY`会导致数据分组,但不会进行任何统计。
  • HAVINGWHERE的区别WHEREGROUP BY之前过滤数据,HAVINGGROUP BY后过滤分组数据。如果需要基于聚合条件进行过滤,应使用HAVING
  • NULL值的处理:在GROUP BY中,NULL会被视为一个单独的组。如果某列包含NULL值,则所有的NULL值将被归为一组。
  • 索引优化:在大数据量表上执行GROUP BY操作时,适当的索引可以显著提高性能。特别是当 GROUP BY的列是表的索引列时,查询效率更高。

总结

  GROUP BY是 SQL 查询中非常重要的功能,广泛用于数据汇总、统计和分组操作。通过与聚合函数的结合,能够在不同的业务场景中提供数据分析能力。在使用GROUP BY时,记住其原理、语法以及优化技巧,能够让你更加高效地处理和分析数据。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis 实战篇 ——《黑马点评》(中)

《引言》 (中)篇将接着记录 Redis 实战篇 ——《黑马点评》(上)篇之后的学习内容与笔记,希望大家能够点赞、收藏支持一下 ᕦ(・ㅂ・)ᕤ,谢谢大家。 传送门(上)&…

【2024年华为OD机试】(A卷,100分)- 猜字谜(Java JS PythonC/C++)

一、问题描述 小王设计了一个简单的猜字谜游戏,游戏的谜面是一个错误的单词,比如 nesw,玩家需要猜出谜底库中正确的单词。猜中的要求如下: 对于某个谜面和谜底单词,满足下面任一条件都表示猜中: 变换顺序…

ip属地是根据手机号还是位置

在数字化时代,IP地址作为网络世界中的“门牌号”,其属地信息往往与用户的地理位置紧密相关。然而,关于IP属地是如何确定的,是否依赖于手机号还是实际位置,这一话题时常引发讨论。本文将深入探讨IP属地的确定方式&#…

nginx 实现 正向代理、反向代理 、SSL(证书配置)、负载均衡 、虚拟域名 ,使用其他中间件监控

我们可以详细地配置 Nginx 来实现正向代理、反向代理、SSL、负载均衡和虚拟域名。同时,我会介绍如何使用一些中间件来监控 Nginx 的状态和性能。 1. 安装 Nginx 如果你还没有安装 Nginx,可以通过以下命令进行安装(以 Ubuntu 为例&#xff0…

React性能优化: 使用React.lazy与Suspense提高加载效率

## 1. React.lazy与Suspense简介 在开发React应用程序时,我们经常会遇到需要加载大型组件或者数据的情况。为了提高页面加载的效率,React引入了React.lazy和Suspense这两个特性。 什么是React.lazy? 是React 16.6版本引入的新特性&#xff0c…

Golang笔记——Interface类型

大家好,这里是Good Note,关注 公主号:Goodnote,专栏文章私信限时Free。本文详细介绍Golang的interface数据结构类型,包括基本实现和使用等。 文章目录 Go 语言中的 interface 详解接口定义实现接口空接口 interface{}示…

轨迹优化 | 基于贝塞尔曲线的无约束路径平滑与粗轨迹生成(附ROS C++/Python仿真)

目录 0 专栏介绍1 从路径到轨迹2 基于贝塞尔曲线的粗轨迹生成2.1 路径关键点提取2.2 路径点航向角计算2.3 贝塞尔曲线轨迹生成 3 算法仿真3.1 ROS C仿真3.2 Python仿真 0 专栏介绍 🔥课设、毕设、创新竞赛必备!🔥本专栏涉及更高阶的运动规划…

理解STC15F2K60S2单片机的最小电路

一、STC15F2K60S2与51单片机的区别 STC15F2K60S2和51单片机虽然都基于8051内核,但在多个方面存在显著区别: 1. CPU性能: - STC15F2K60S2:采用增强型8051 CPU,1T单时钟/机器周期,速度比普通8051快8-12倍…

VSCode 搜索 搜不到

VSCode 搜索 搜不到 今天打开一个新的工作目录之后 ctrl P 搜文件 搜不到 经观察后发现 当我搜索时候, 右侧搜索按钮有一个时钟标识,疑似 搜索的范围 是最近打开内容。 经过和全局搜索的编辑器对比设置后发现,把设置中 下图中 选项去掉勾选…

软件测试 —— Selenium常用函数

软件测试 —— Selenium常用函数 操作测试对象点击/提交对象 click()模拟按键输入 send_keys("")清除文本内容 clear() 模拟用户键盘行为 Keys包示例用法 获取文本信息 textget_attribute("属性名称") 获取当前页面标题 title获取当前页面的 url current_u…

Vue 学习之旅:核心技术学习总结与实战案例分享(vue指令下+计算属性+侦听器)

Vue 学习之旅:核心技术学习总结与实战案例分享 文章目录 Vue 学习之旅:核心技术学习总结与实战案例分享一、指令补充(一)指令修饰符(二)v-bind 对样式操作的增强(三)v-model 应用于其…

UE5 打包项目

UE5 打包项目 flyfish 通过 “文件”->“打开项目”,然后在弹出的对话框中选择项目文件(通常是以.uproject为后缀的文件) 选择目标平台: 在 UE5 主界面中,找到 “平台”(Platforms)。根据…

1. Doris分布式环境搭建

一. 环境准备 本次测试集群采用3台机器hadoop1、hadoop2、hadoop3, Frontend和Backend部署在同一台机器上,Frontend部署3台组成高可用,Backend部署3个节点,组成3副本存储。 主机IP操作系统FrontendBackendhadoop1192.168.47.128Centos7Foll…

win10电脑 定时关机

win10电脑 定时关机 https://weibo.com/ttarticle/p/show?id2309405110707766296723 二、使用任务计划程序设置定时关机打开任务计划程序: 按下“Win S”组合键,打开搜索框。 在搜索框中输入“任务计划程序”,然后点击搜索结果中的“任务…

day07_Spark SQL

文章目录 day07_Spark SQL课程笔记一、今日课程内容二、Spark SQL函数定义(掌握)1、窗口函数2、自定义函数背景2.1 回顾函数分类标准:SQL最开始是_内置函数&自定义函数_两种 2.2 自定义函数背景 3、Spark原生自定义UDF函数3.1 自定义函数流程&#x…

Hadoop3.x 万字解析,从入门到剖析源码

💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长…

Java 实现 Elasticsearch 查询当前索引全部数据

Java 实现 Elasticsearch 查询当前索引全部数据 需求背景通常情况Java 实现查询 Elasticsearch 全部数据写在最后 需求背景 通常情况下,Elasticsearch 为了提高查询效率,对于不指定分页查询条数的查询语句,默认会返回10条数据。那么这就会有…

Elasticsearch ES|QL 地理空间索引加入纽约犯罪地图

可以根据地理空间数据连接两个索引。在本教程中,我将向你展示如何通过混合邻里多边形和 GPS 犯罪事件坐标来创建纽约市的犯罪地图。 安装 如果你还没有安装好自己的 Elasticsearch 及 Kibana 的话,请参考如下的链接来进行安装。 如何在 Linux&#xff0…

C#学习笔记 --- 简单应用

1.operator 运算符重载:使自定义类可以当做操作数一样进行使用。规则自己定。 2.partial 分部类: 同名方法写在不同位置,可以当成一个类使用。 3.索引器:使自定义类可以像数组一样通过索引值 访问到对应的数据。 4.params 数…

【Flink】Flink内存管理

Flink内存整体结构图: JobManager内存管理 JVM 进程总内存(Total Process Memory)Flink总内存(Total Flink Memory):JVM进程总内存减去JVM Metaspace(元空间)和JVM Overhead(运行时开销)上图解释: JVM进程总内存为2G;JVM运行时开销(JVM Overh…