3-1 group by 详细用法教程
在 SQL 中,GROUP BY 子句用于将查询结果按照一个或多个列进行分组,
通常与聚合函数(如 SUM、COUNT、AVG 等)结合使用,以汇总每个组的数据。
一、基本语法
SELECT
column1, -- 必须出现在GROUP BY中或使用聚合函数
column2, -- 必须出现在GROUP BY中或使用聚合函数
aggregate_function(column3) -- 聚合函数(如SUM、COUNT等)
FROM
table_name
WHERE
condition -- 可选过滤条件
GROUP BY
column1, column2 -- 按这些列分组
ORDER BY
column1; -- 可选排序
二、核心概念
分组逻辑
将表中具有相同值的行分为一组,对每组数据执行聚合操作。
2. 常用聚合函数
SUM():求和COUNT():计数AVG():平均值MAX():最大值MIN():最小值GROUP_CONCAT()(MySQL):连接分组内的值
三、示例 1:按单列分组
假设 orders 表结构:
order_id
customer_id
amount
status
1
101
200
completed
2
101
150
pending
3
102
300
completed
需求:统计每个客户的订单总数和总金额
SELECT
customer_id,
COUNT(*) AS order_count, -- 每个客户的订单数
SUM(amount) AS total_amount -- 每个客户的总金额
FROM
orders
GROUP BY
customer_id;
结果:
customer_id
order_count
total_amount
101
2
350
102
1
300
四、示例 2:按多列分组
需求:统计每个客户、每种状态的订单数
SELECT
customer_id,
status,
COUNT(*) AS order_count
FROM
orders
GROUP BY
customer_id, status; -- 先按客户分组,再按状态分组
结果:
customer_id
status
order_count
101
completed
1
101
pending
1
102
completed
1
五、示例 3:结合 WHERE 子句过滤
需求:统计金额大于 100 的订单,按客户分组
SELECT
customer_id,
COUNT(*) AS order_count,
SUM(amount) AS total_amount
FROM
orders
WHERE
amount > 100 -- 先过滤金额大于100的订单
GROUP BY
customer_id;
六、示例 4:使用 HAVING 过滤分组结果
需求:找出总订单金额超过 200 的客户
SELECT
customer_id,
SUM(amount) AS total_amount
FROM
orders
GROUP BY
customer_id
HAVING
SUM(amount) > 200; -- 对分组后的结果进行过滤
关键区别:
WHERE:过滤行数据(在分组前执行)HAVING:过滤分组结果(在分组后执行)
七、示例 5:使用聚合函数的嵌套
需求:计算每个客户的平均订单金额,并保留两位小数
SELECT
customer_id,
ROUND(AVG(amount), 2) AS avg_amount -- 计算平均值并四舍五入
FROM
orders
GROUP BY
customer_id;
八、示例 6:分组连接字符串(MySQL)假设
products 表:
category
product_name
Electronics
iPhone
Electronics
Laptop
Clothing
T-Shirt
需求:列出每个类别下的所有产品
SELECT
category,
GROUP_CONCAT(product_name SEPARATOR ', ') AS products
FROM
products
GROUP BY
category;
结果:
category
products
Electronics
iPhone, Laptop
Clothing
T-Shirt
九、注意事项
SELECT 中的列限制
非聚合列必须全部出现在 GROUP BY 中(SQL 标准要求)。
SELECT
customer_id,
status, -- 必须出现在GROUP BY中
COUNT(*)
FROM
orders
GROUP BY
customer_id; -- 错误!缺少status列
NULL 值处理
GROUP BY 会将 NULL 视为一组:
SELECT
column_with_null,
COUNT(*)
FROM
table
GROUP BY
column_with_null; -- NULL会单独成为一组
分组顺序
多列分组时,先按第一列分组,再按第二列分组,以此类推。
十、常见错误
忘记 GROUP BY
SELECT
customer_id,
SUM(amount) -- 错误!缺少GROUP BY子句
FROM
orders;
非聚合列未包含在 GROUP BY 中
SELECT
customer_id,
status, -- 未包含在GROUP BY中
SUM(amount)
FROM
orders
GROUP BY
customer_id; -- 错误!
十一、最佳实践
明确分组目的
先确定需要按哪些列分组,再选择合适的聚合函数。
使用别名提高可读性
SELECT
customer_id AS customer,
COUNT(*) AS orders
FROM
orders
GROUP BY
customer_id;
结合 ORDER BY 排序
SELECT
customer_id,
SUM(amount) AS total
FROM
orders
GROUP BY
customer_id
ORDER BY
total DESC; -- 按总金额降序排列
十二、进阶用法:ROLLUP 和 CUBE
1. ROLLUP
生成分组的小计和总计:
SELECT
customer_id,
status,
SUM(amount)
FROM
orders
GROUP BY
customer_id, status WITH ROLLUP; -- 添加汇总行
2. CUBE
生成所有可能的分组组合:
SELECT
customer_id,
status,
SUM(amount)
FROM
orders
GROUP BY
CUBE(customer_id, status); -- 生成所有组合的汇总
通过 GROUP BY,你可以高效地对数据进行分组和聚合,提取有价值的统计信息。合理使用聚合函数和过滤条件,能让你的查询更加灵活和强大。