查询1990年后成立公司员工总数的SQL语法错误排查
解决SQL GROUP BY + HAVING的1055错误,实现1990年后成立公司员工总数统计
错误原因
当sql_mode=only_full_group_by启用时,MySQL要求SELECT列表中的所有非聚合列必须出现在GROUP BY子句中,或者与GROUP BY中的列存在函数依赖(比如GROUP BY的列是表的主键,其他列由主键唯一确定)。
你的错误在于:GROUP BY仅指定了c.name,但SELECT列表中包含了未聚合的e.year,数据库无法确认每个分组内的e.year是唯一值,因此触发1055错误。
解决方案
方案1:用WHERE提前筛选(推荐,性能更优)
成立年份是分组前就能确定的筛选条件,直接用WHERE过滤后再分组,同时将e.year加入GROUP BY(因为SELECT中包含它):
SELECT c.name, SUM(c.employees), e.year FROM company AS c JOIN Established AS e ON c.name = e.name WHERE e.year > 1990 GROUP BY c.name, e.year;
如果你的业务逻辑中一个公司对应唯一成立年份,这样分组后每个公司会返回一行,结果完全符合需求,且避免了错误。
方案2:用聚合函数配合HAVING筛选
如果必须使用HAVING(比如需要基于聚合结果二次筛选),可以对e.year使用聚合函数(如MAX()或MIN(),假设一个公司只有一个成立年份,聚合后结果不变),同时SELECT列表中也使用对应的聚合函数:
SELECT c.name, SUM(c.employees), MAX(e.year) AS established_year FROM company AS c JOIN Established AS e ON c.name = e.name GROUP BY c.name HAVING MAX(e.year) > 1990;
这样SELECT中的MAX(e.year)是聚合结果,符合only_full_group_by的要求,HAVING子句也通过聚合函数筛选成立年份。
额外说明
- 优先使用WHERE筛选分组前的条件,数据库会先过滤掉不符合条件的行,再执行分组操作,性能远高于先分组再用HAVING筛选。
- 如果你的业务中
company.name是唯一主键,且Established.name是外键关联到company.name,可以通过修改表结构添加外键约束,让数据库识别e.year与c.name的函数依赖,这样可以不用在GROUP BY中加入e.year(但不推荐依赖这种隐式规则,显式指定GROUP BY列更安全)。
内容的提问来源于stack exchange,提问作者Tapas P
相关产品推荐
相关产品推荐

