MySQL GROUP BY 和 HAVING 子句示例

⚡ 智能摘要

SQL 的 GROUP BY 和 HAVING 子句可以将详细行转换为汇总报告。GROUP BY 将具有相同值的行合并为一个组,每组一行;而 HAVING 在应用 COUNT 等聚合函数后,对这些组进行筛选。

  • 📊 核心宗旨: GROUP BY 将具有相同值的行分组,并为每个分组项返回一行。
  • 🧩 单柱组ping: 的Grouping 按性别划分的成员表将九行合并为两行,一行代表女性,一行代表男性。
  • 🔗 多列组ping: 的Grouping 在两列中,当任一列的值不同时,该行被视为唯一行,因此只有完全重复的行才会合并。
  • 🧮 聚合配对: 计数、求和、 AVGMIN、MAX 和 MIN 分别计算每个组的一个值,从而生成汇总报告。
  • 🚦 拥有 vs. 地点: WHERE 筛选组之前的行ping之后,HAVING 会筛选分组,并且只有 HAVING 才会接受聚合结果。
  • ⚠️ 严格模式警告: 在 ONLY_FULL_GROUP_BY 下,每个选定的列都必须进行分组或封装在聚合函数中。

SQL GROUP BY 和 HAVING 子句

什么是 SQL GROUP BY 子句?

GROUP BY 子句是一个 SQL 命令,用于 将具有相同值的行分组它写在 SELECT 语句中,通常与聚合函数一起使用,以从数据库中生成汇总报告。

它的作用就是这样:它 汇总数据 存储在数据库中。包含 GROUP BY 子句的查询称为分组查询,它们为每个分组项返回一行。

SQL GROUP BY 语法

既然该子句的用途已经明确,让我们来看看基本分组查询的语法。

SELECT statements... GROUP BY column_name1[, column_name2, ...] [HAVING condition];

点击这里

  • SELECT 语句…是标准 SQL SELECT 命令查询。
  • 通过...分组 列名1”是执行组操作的条款ping 基于 column_name1。
  • [, column_name2, …]“ ”是可选的,当组为 时表示其他列名ping 在多列上进行操作。
  • [患有某种疾病]“ ”是可选的,用于限制受 GROUP BY 子句影响的行。它类似于 WHERE 子句只是它是在组之后应用的。ping.

的Grouping 使用单列

要快速了解 SQL GROUP BY 子句的效果,最好的方法是比较未分组查询和分组查询。首先,编写一个简单的查询,返回 members 表中所有性别条目。

SELECT `gender` FROM `members`;
性别
(女)
(女)
(男)
(女)
(男)
(男)
(男)
(男)
(男)

返回九行结果,且每个值都重复出现。假设我们想要获取性别的唯一值。以下查询添加了 GROUP BY 子句。

SELECT `gender` FROM `members` GROUP BY `gender`;

在以下位置执行上述脚本 MySQL 工作台 针对 myflixdb 我们得到以下结果。

性别
(女)
(男)

请注意,由于表中仅包含两种性别类型,因此只返回了两行数据。GROUP BY 子句将所有“男性”成员分组在一起,并返回一行数据;对“女性”成员也执行了相同的操作。

的Grouping 使用多列

的Grouping 单列数据对于实际报表来说通常过于粗略。GROUP BY 子句接受以逗号分隔的列列表,每个分组由这些列的值组合而成。

假设我们想要一个电影类别 ID 值及其对应的电影上映年份列表。首先观察一下这个简单查询的输出结果。

SELECT `category_id`, `year_released` FROM `movies`;
类别编号 发行年份
1 2011
2 2008
2008
2010
8 2007
6 2007
6 2007
8 2005
2012
7 1920
8
8 1920

高亮显示的行表明结果中包含重复项。使用 GROUP BY 子句执行相同的查询即可删除这些重复项。

SELECT `category_id`, `year_released` FROM `movies` GROUP BY `category_id`, `year_released`;

在以下位置执行上述脚本 MySQL 使用 Workbench 对 myflixdb 进行测试,我们得到了如下所示的结果。

类别编号 发行年份
2008
2010
2012
1 2011
2 2008
6 2007
7 1920
8 1920
8 2005
8 2007

GROUP BY 子句同时作用于 category_id 和 year_released 来识别 独特的 行。2007 年第 6 类的两行重复数据合并为一行。

经验法则: 如果类别 ID 相同但发布年份不同,则该行被视为唯一记录。如果多行的类别 ID 和发布年份相同,则这些行被视为重复记录,仅显示其中一条。

的Grouping 和聚合函数

删除重复项很有用,但群组的真正力量在于ping 当它与……配对时出现 聚合函数聚合函数为每个组计算一个值:COUNT 函数计算行数,SUM 函数将值相加, AVGMIN 和 MAX 描述了价差。

假设我们想要获取数据库中男性和女性成员的总数。下面的脚本可以实现这一点。

SELECT `gender`, COUNT(`membership_number`) FROM `members` GROUP BY `gender`;

在以下位置执行上述脚本 MySQL 使用 Workbench 对 myflixdb 数据库进行测试,得到以下结果。

性别 COUNT(`membership_number`)
(女) 3
(男) 6

这些行按唯一的性别值分组,每个组内的行数由 COUNT 聚合函数统计。九条成员记录合并为两行汇总数据。

使用 HAVING 子句限制查询结果

的Grouping并非表格中的每一行都需要包含特定条件。有时,报表必须符合特定条件,而这正是 HAVING 子句的作用。

假设我们想知道电影类别 ID 为 8 的所有上映年份。下面的脚本可以实现这一结果。

SELECT * FROM `movies` GROUP BY `category_id`, `year_released` HAVING `category_id` = 8;

在以下位置执行上述脚本 MySQL 使用 Workbench 对 myflixdb 进行测试,我们得到了如下所示的结果。

电影 ID 标题 导向器 发行年份 类别编号
9 Honey moonERS 约翰舒尔茨 2005 8
5 爸爸的小女孩 2007 8

根据 HAVING 条件,只有类别 ID 为 8 的电影才被保留。

警告: MySQL 5.7 及更高版本默认启用 ONLY_FULL_GROUP_BY 模式,在该模式下,带有 GROUP BY 子句的 SELECT * 查询将被拒绝,因为 movie_id、title 和 director 既没有分组也没有聚合。在生产环境中,请显式命名分组列,例如: SELECT category_id, year_released FROM movies GROUP BY category_id, year_released HAVING category_id = 8;

WHERE、HAVING、GROUP BY 和 ORDER BY 是不同的组合。

初学者经常混淆这四个子句,因为它们都会影响结果集。区别在于…… ,尤其是 MySQL 它们依次执行:WHERE 在行分组之前执行,HAVING 在行分组之后执行,ORDER BY 最后执行。

条款 它做什么 运行时 接受聚合函数
NeoCity 在进行任何分组之前,先筛选单个行。ping. 在 GROUP BY 之前 没有
通过...分组 将具有相同值的行合并为每组的一行。 在 WHERE 之后 不适用
HAVING 筛选由 GROUP BY 生成的分组。 在 GROUP BY 之后 是的,例如 HAVING COUNT(*) > 2
ORDER BY 对经过前面几个子句处理后的行进行排序。 姓氏 是的,聚合别名可以排序。

实际后果是性能问题。使用 WHERE 进行过滤会删除组之前的行。ping 工作开始了,因此不依赖于聚合结果的条件应该放在 WHERE 而不是 HAVING 中。

常见问题

是的。单独使用 GROUP BY 子句会为每个唯一值返回一行,其去重方式与 SELECT DISTINCT 子句非常相似。只有当每个组都需要计算值时才需要使用聚合函数。

当选定的列既未在 GROUP BY 中列出,也未包含在聚合函数中时,会出现此错误。 MySQL 由于无法确定要为该组显示该列的哪个值,因此拒绝查询。

COUNT(*) 统计组中每一行的数量。COUNT(column) 只统计该列不为空的行数。 因此,当该列包含缺失值时,这两个数字就会有所不同。

是的。诸如此类的工具中都内置了人工智能助手。 MySQL 工作台 将“按性别划分的成员”之类的请求转换为分组查询。检查分组ping 自己撰写专栏,因为错误的群体ping 得出的总数看起来合情合理,但实际上是错误的。

通常情况下,是的。人工智能查询助手会标记出诸如以下情况之类的经典原因: 注册 在分组之前乘以行ping或者,也可以使用 HAVING 子句而不是 WHERE 子句中的筛选条件。最终的判断权仍然掌握在了解数据的人手中。

总结一下这篇文章: