SQL怎么用AVG和GROUP BY计算不同地区平均工资?

来源:PHP教程作者:林小满头衔:网络博主
导读:本期聚焦于小伙伴创作的《SQL怎么用AVG和GROUP BY计算不同地区平均工资?》,敬请观看详情。做人事报表或经营分析时,常常要把员工薪资按省份或城市拆开看均值。直接用AVG算全表会得到整体水平,掩盖了区域差异。正确做法是在SELECT里写AVG(salary),配合GROUP BY region把数据分组,数据库会先按地区归类再分别求平均。若地区字段有空值,该行会被单独成组,可用COALESCE转成未知。还想看每个组的人数和最高薪,就一并写COUNT与MAX。下面讲清写法、性能与常见错法。

在关系型数据库里,统计不同地区的平均工资是典型的分组聚合需求。核心思路是利用GROUP BY把具有相同地区值的记录划分到同一个桶中,再对每个桶使用AVG函数计算薪资的平均值。这种方式比在应用层先查出全量数据再自己写循环求平均要高效得多,因为分组和聚合都在数据库引擎内部以集合运算完成,既能减少网络传输,也能借助索引加速。

SQL怎么用AVG和GROUP BY计算不同地区平均工资?

基础语法与可运行示例

最基础的写法是在SELECT子句中同时列出分组列和聚合函数。假设我们有一张employee表,其中包含region(地区)和salary(月薪)两个字段。下面的语句会按region分组,并算出每个地区的不重复平均薪资。

需要注意,出现在SELECT中但没有被聚合的列,必须全部写在GROUP BY后面,否则标准SQL会报错。某些数据库如MySQL在宽松模式下允许非聚合列出现在SELECT里,但结果不可控,生产环境应严格遵循标准写法。另外,AVG默认忽略NULL值,如果某员工salary为NULL,他不会参与该地区的平均计算,但也不会从分组中消失。

SELECT
    region,
    AVG(salary) AS avg_salary,
    COUNT(*) AS emp_count
FROM employee
GROUP BY region
ORDER BY avg_salary DESC;

上面这段代码中,COUNT(*)统计的是每个地区的总行数,包括salary为NULL的人;如果想只看有薪资的人数,可写成COUNT(salary)。ORDER BY放在最后,用于对计算结果排序,数据库通常会在分组聚合完成后再执行排序。

处理空地区与多维度拆解

真实业务里,region字段可能存在NULL,代表地区信息缺失。GROUP BY会把所有NULL归为同一组,输出一行region为NULL的平均工资,这容易让读报表的人困惑。我们可以用COALESCE把NULL转成明确标记,使结果更清晰。

此外,有时不仅要按大区,还要按城市或部门交叉统计。这时GROUP BY后面可以写多个列,数据库会按照列的顺序做复合分组。例如先按region再按city,就能得到每个大区下面各个城市的平均工资。也可以结合CASE WHEN做自定义分区,比如把低于某值的薪资单独归类,但那样AVG仍是针对原值,只是分组标签变了。

SELECT
    COALESCE(region, '未知地区') AS region_label,
    city,
    AVG(salary) AS avg_salary
FROM employee
GROUP BY region, city
ORDER BY region_label, avg_salary DESC;

在多列分组时,索引设计很关键。如果经常在region、city上做GROUP BY,建立联合索引(region, city)能让数据库用松散索引扫描快速得到分组边界,避免临时表落盘。没有合适索引时,数据量一大就会触发filesort或外部排序,响应明显变慢。

常见错误与性能优化思路

新手常犯的一类错误是把WHERE和HAVING混淆。WHERE在分组前过滤行,比如只想统计2023年入职的员工,应写WHERE hire_date >= '2023-01-01';而HAVING用于过滤分组后的结果,例如只保留平均薪资大于一万的地区,要写HAVING AVG(salary) > 10000。把聚合条件放进WHERE会导致语法错误,因为WHERE执行时分组还没发生。

另一个性能误区是认为AVG一定比SUM/COUNT慢。实际上在大多数引擎中,AVG只是SUM除以COUNT的语法糖,并不会多扫一遍数据。真正的瓶颈往往是分组字段基数过高或缺少索引。对于超大型表,可考虑先按地区汇总到物化视图,或者只用必要列避免宽表读取。如下示例展示了HAVING的正确用法。

SELECT
    region,
    AVG(salary) AS avg_salary
FROM employee
WHERE status = 1
GROUP BY region
HAVING AVG(salary) > 10000;

最后补充一点,如果地区名称本身不规范,比如“北京”和“北京市”被当成两个值,GROUP BY会识别出两组。此时应先在ETL阶段做字典映射统一,或者在SQL里用UPDATE清理维度表,否则统计出的平均工资会出现人为分裂,误导管理决策。通过上面这些写法与注意点,就能用AVG加GROUP BY稳定准确地算出不同地区平均工资。

SQLAVGGROUP_BY修改时间:2026-08-13 20:27:28

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。