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,玩家需要猜出谜底库中正确的单词。猜中的要求如下: 对于某个谜面和谜底单词,满足下面任一条件都表示猜中: 变换顺序…

git提交大文件

如果有文件大小大于 100M,GitHub 是会被限制推送到仓库中的,大概率情况会显示下面的错误: remote: Resolving deltas: 100% (3601/3601), done.remote: error: Trace: aea1f450da6f2ef7bfce457c715d0fbb9b0f6d428fdca80233aff34b601ff59brem…

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

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

SpringBoot之OriginTrackedPropertiesLoader类源码学习

源码解析 /*** 作用是从给定的资源(如文件或输入流)中加载 .properties 文件,* 并将属性键值对转换为带有来源信息(origin)的 OriginTrackedValue 对象。*/ public class OriginTrackedPropertiesLoader {private fin…

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…

开发人员学习书籍推荐(C#、Python方向)

作为一名开发人员,持续学习和提升自己的技术水平是至关重要的。如今,技术不断更新换代,新的开发框架、语言和工具层出不穷。对于刚入行的开发者或希望深入某一领域的工程师来说,选对书籍是学习的捷径之一。本篇文章将推荐一些经典…

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倍…

微信小程序获取当前页面路径,登录成功后重定向回原页面

🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回&#…

Linux学习指南与资料分享

Linux学习资料 Linux学习资料 Linux学习资料 基础入门 了解 Linux 基础概念: Linux 是开源类 Unix 操作系统,由内核、Shell 和应用程序组成。学习时要了解其开源、稳定、安全等特性,以及多用户、多任务的特点。 选择并安装 Linux 发行版…

VSCode 搜索 搜不到

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

软件测试 —— Selenium常用函数

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

【9.1】Golang后端开发系列--Gin快速入门指南

文章目录 一、引言 🌟二、Gin 框架概述 📖(一)什么是 Gin(二)为什么选择 Gin 三、安装 Gin 框架 📦(一)安装 Go 语言环境(二)使用 Go Modules 安装…

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

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

OpenCV相机标定与3D重建(55)通用解决 PnP 问题函数solvePnPGeneric()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 根据3D-2D点对应关系找到物体的姿态。 cv::solvePnPGeneric 是 OpenCV 中一个更为通用的函数,用于解决 PnP 问题。它能够返回多个可能…

UE5 打包项目

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

1. Doris分布式环境搭建

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