2021-11-05 21:59:26
GROUP BY 多列用于根据多个字段组合进行分组统计,只有所有指定列的值完全相同才会归为一组,以下是具体用法和操作技巧:
基本概念与示例GROUP BY 多列时,SQL 会按照这些列的组合值分组。例如,统计订单表中每个地区每种产品的总销售额:
SELECT region, product_id, SUM(amount) AS total_amount FROM orders GROUP BY region, product_id;
分组顺序的影响
逻辑结果:GROUP BY region, product_id 和 GROUP BY product_id, region 的聚合结果行数相同,但分组逻辑顺序不同。
性能建议:
将基数高的列(唯一值较多的列)放在前面,例如 GROUP BY product_id, region(若 product_id 唯一值更多)。
若后续有 ORDER BY,可复用 GROUP BY 顺序以减少排序开销。

常见错误与注意事项
SELECT 字段限制:非聚合字段必须出现在 GROUP BY 中。例如,以下查询会报错:SELECT region, product_id, product_name, SUM(amount) FROM orders GROUP BY region, product_id; -- 错误:product_name 未包含在 GROUP BY 或聚合函数中
避免过度分组:加入不必要的列会导致分组粒度过细,失去统计意义。例如,按地区和年份统计销售额时,无需加入“月份”列。
NULL 值处理:在大多数数据库中,NULL 值被视为相等并归为同一组。例如,以下查询会将所有 region 为 NULL 的记录分为一组:SELECT region, COUNT(*) FROM orders WHERE region IS NULL GROUP BY region; -- 结果为 1 组(所有 NULL 值)
实际应用技巧
结合 HAVING 筛选分组:例如,筛选总销售额超过 1 万的地区+产品组合:SELECT region, product_id, SUM(amount) AS total_amount FROM orders GROUP BY region, product_id HAVING SUM(amount) > 10000;
配合窗口函数分析:在不压缩行数的情况下获取分组统计数据。例如,查看每条订单记录所在分组的总销售额:SELECT region, product_id, amount, SUM(amount) OVER (PARTITION BY region, product_id) AS total_by_group FROM orders;

总结:GROUP BY 多列的核心是按列组合值分组,需注意字段限制、避免过度分组,并可结合 HAVING 或窗口函数提升查询灵活性。合理设计分组顺序能优化性能,NULL 值处理需根据业务需求调整。