前言很多新手学完聚合函数后不知道怎么“按类别统计”——比如按性别统计用户数、按用户分组统计订单金额这时候就需要用到GROUP BY 分组查询。而 HAVING 则是配合 GROUP BY 使用用于「过滤分组后的结果」和WHERE的区别WHERE过滤行HAVING过滤分组。本篇用通俗的逻辑实战案例讲透GROUP BY和HAVING的用法、区别以及新手最容易踩的坑看完就能上手分组统计。继续使用 user 表和 order 表测试数据沿用之前的。一、GROUP BY按指定字段分组核心逻辑将数据按「指定字段的值」分成多个小组每个小组进行聚合统计搭配COUNT、SUM、AVG使用。简单说按性别分组 → 分成“男”“女”两个小组分别统计每个小组的用户数。1. 基础分组单字段分组-- 案例1按性别分组统计每个性别的用户数 SELECT gender, -- 分组字段必须放在SELECT后面和聚合函数并列 COUNT(*) AS user_count -- 聚合统计 FROM user GROUP BY gender; -- 案例2按用户分组user_id统计每个用户的订单数和订单总金额 SELECT user_id, COUNT(*) AS order_count, -- 订单数 SUM(amount) AS total_amount -- 订单总金额 FROM order GROUP BY user_id;2. 进阶分组多字段分组当单字段分组无法满足需求时可按多个字段分组先按第一个字段分组第一个字段值相同时按第二个字段分组。-- 案例按性别和年龄分组统计每个组合的用户数 SELECT gender, age, COUNT(*) AS user_count FROM user GROUP BY gender, age; -- 先按gender分组再按age分组GROUP BY 核心规则必记✅ SELECT 后面的字段只能是「分组字段」和「聚合函数」不能出现其他无关字段❌ 错误示例SELECT name, gender, COUNT(*) FROM user GROUP BY gender;name不是分组字段也不是聚合函数。二、HAVING过滤分组后的结果HAVING 和 WHERE 都是用于过滤但适用场景完全不同- WHERE过滤「分组前的行」不能用聚合函数- HAVING过滤「分组后的结果」可以用聚合函数。1. 基础用法过滤分组结果-- 案例1按性别分组统计用户数只显示用户数2的分组 SELECT gender, COUNT(*) AS user_count FROM user GROUP BY gender HAVING user_count 2; -- 过滤分组结果用户数2 -- 案例2按用户分组统计订单总金额只显示总金额100的用户 SELECT user_id, SUM(amount) AS total_amount FROM order GROUP BY user_id HAVING total_amount 100;2. 组合使用WHERE GROUP BY HAVING逻辑顺序先WHERE过滤行 → 再GROUP BY分组 → 最后HAVING过滤分组。-- 案例按用户分组统计年龄20的用户的订单数只显示订单数1的用户 SELECT o.user_id, u.name, COUNT(o.order_id) AS order_count FROM order o LEFT JOIN user u ON o.user_id u.id -- 关联用户表 WHERE u.age 20 -- 先过滤年龄20的用户分组前行过滤 GROUP BY o.user_id, u.name -- 按用户分组关联表需包含所有非聚合字段 HAVING order_count 1; -- 再过滤订单数1的分组三、WHERE 和 HAVING 核心区别必背对比项WHEREHAVING过滤时机分组之前过滤行分组之后过滤分组是否支持聚合函数不支持支持适用场景过滤具体的行数据过滤分组后的统计结果四、新手常见坑1. ❌ 错误SELECT 中出现非分组、非聚合的字段如前面的name字段未分组也未聚合✅ 正确要么将该字段加入GROUP BY要么用聚合函数包裹如MAX(name)2. ❌ 错误用WHERE过滤聚合结果如 WHERE COUNT(*) 2✅ 正确过滤聚合结果必须用HAVING3. ❌ 错误GROUP BY 后面的字段和SELECT中的分组字段不一致✅ 正确GROUP BY 字段需和SELECT中的非聚合字段完全一致。五、总结1. GROUP BY按指定字段分组搭配聚合函数实现“按类别统计”2. HAVING过滤分组后的结果支持聚合函数和WHERE分工明确3. 组合顺序SELECT → FROM → WHERE → GROUP BY → HAVING。
GROUP BY分组查询+HAVING过滤,一文搞懂分组逻辑
前言很多新手学完聚合函数后不知道怎么“按类别统计”——比如按性别统计用户数、按用户分组统计订单金额这时候就需要用到GROUP BY 分组查询。而 HAVING 则是配合 GROUP BY 使用用于「过滤分组后的结果」和WHERE的区别WHERE过滤行HAVING过滤分组。本篇用通俗的逻辑实战案例讲透GROUP BY和HAVING的用法、区别以及新手最容易踩的坑看完就能上手分组统计。继续使用 user 表和 order 表测试数据沿用之前的。一、GROUP BY按指定字段分组核心逻辑将数据按「指定字段的值」分成多个小组每个小组进行聚合统计搭配COUNT、SUM、AVG使用。简单说按性别分组 → 分成“男”“女”两个小组分别统计每个小组的用户数。1. 基础分组单字段分组-- 案例1按性别分组统计每个性别的用户数 SELECT gender, -- 分组字段必须放在SELECT后面和聚合函数并列 COUNT(*) AS user_count -- 聚合统计 FROM user GROUP BY gender; -- 案例2按用户分组user_id统计每个用户的订单数和订单总金额 SELECT user_id, COUNT(*) AS order_count, -- 订单数 SUM(amount) AS total_amount -- 订单总金额 FROM order GROUP BY user_id;2. 进阶分组多字段分组当单字段分组无法满足需求时可按多个字段分组先按第一个字段分组第一个字段值相同时按第二个字段分组。-- 案例按性别和年龄分组统计每个组合的用户数 SELECT gender, age, COUNT(*) AS user_count FROM user GROUP BY gender, age; -- 先按gender分组再按age分组GROUP BY 核心规则必记✅ SELECT 后面的字段只能是「分组字段」和「聚合函数」不能出现其他无关字段❌ 错误示例SELECT name, gender, COUNT(*) FROM user GROUP BY gender;name不是分组字段也不是聚合函数。二、HAVING过滤分组后的结果HAVING 和 WHERE 都是用于过滤但适用场景完全不同- WHERE过滤「分组前的行」不能用聚合函数- HAVING过滤「分组后的结果」可以用聚合函数。1. 基础用法过滤分组结果-- 案例1按性别分组统计用户数只显示用户数2的分组 SELECT gender, COUNT(*) AS user_count FROM user GROUP BY gender HAVING user_count 2; -- 过滤分组结果用户数2 -- 案例2按用户分组统计订单总金额只显示总金额100的用户 SELECT user_id, SUM(amount) AS total_amount FROM order GROUP BY user_id HAVING total_amount 100;2. 组合使用WHERE GROUP BY HAVING逻辑顺序先WHERE过滤行 → 再GROUP BY分组 → 最后HAVING过滤分组。-- 案例按用户分组统计年龄20的用户的订单数只显示订单数1的用户 SELECT o.user_id, u.name, COUNT(o.order_id) AS order_count FROM order o LEFT JOIN user u ON o.user_id u.id -- 关联用户表 WHERE u.age 20 -- 先过滤年龄20的用户分组前行过滤 GROUP BY o.user_id, u.name -- 按用户分组关联表需包含所有非聚合字段 HAVING order_count 1; -- 再过滤订单数1的分组三、WHERE 和 HAVING 核心区别必背对比项WHEREHAVING过滤时机分组之前过滤行分组之后过滤分组是否支持聚合函数不支持支持适用场景过滤具体的行数据过滤分组后的统计结果四、新手常见坑1. ❌ 错误SELECT 中出现非分组、非聚合的字段如前面的name字段未分组也未聚合✅ 正确要么将该字段加入GROUP BY要么用聚合函数包裹如MAX(name)2. ❌ 错误用WHERE过滤聚合结果如 WHERE COUNT(*) 2✅ 正确过滤聚合结果必须用HAVING3. ❌ 错误GROUP BY 后面的字段和SELECT中的分组字段不一致✅ 正确GROUP BY 字段需和SELECT中的非聚合字段完全一致。五、总结1. GROUP BY按指定字段分组搭配聚合函数实现“按类别统计”2. HAVING过滤分组后的结果支持聚合函数和WHERE分工明确3. 组合顺序SELECT → FROM → WHERE → GROUP BY → HAVING。