Laravel查询构建器GROUP BY employee_id触发MySQL 1055错误求助(Bluehost共享主机环境)
employee_id触发only_full_group_by错误的问题 看起来你遇到的问题根源在于子查询中SELECT的列与GROUP BY子句不兼容,即使关闭了Laravel的strict模式,可能因为Bluehost共享主机的全局SQL模式配置或者查询结构本身的问题,导致only_full_group_by规则依然生效。下面是具体的分析和解决方案:
问题分析
错误提示里明确指出:Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'affixpro_jobhut.work_experiences.id'。这是因为你在exists子查询中使用了select *,它会返回work_experiences表的所有列(包括id这种非聚合列),而你GROUP BY的是employee_id,这违反了only_full_group_by的规则——所有非聚合列必须出现在GROUP BY中,或者与GROUP BY列函数依赖。
而直接在phpMyAdmin中运行的SQL是只查询employee_id和计算的差值,没有包含其他非聚合列,所以不会触发错误;当你GROUP BY id时,因为id是主键,所有列都依赖于它,所以规则允许。
解决方案
1. 修正子查询的SELECT语句
把exists子查询中的select *改为只选择employee_id(或者用select 1,因为exists只需要判断存在性,不需要具体列),这样就不会包含非聚合的列,避免触发规则:
// 调整exists里的子查询结构 ->exists(function ($query) use ($filterOverralExperienceA, $filterOverralExperienceB) { $query->select('employee_id') // 替换原来的select * ->from('work_experiences') ->whereColumn('employees.id', 'work_experiences.employee_id') ->groupBy('employee_id') ->havingRaw('FLOOR(DATEDIFF(MAX(to_date), MIN(from_date))/365) >= ?', [$filterOverralExperienceA]) ->havingRaw('FLOOR(DATEDIFF(MAX(to_date), MIN(from_date))/365) <= ?', [$filterOverralExperienceB]); })
2. 确保数据库SQL模式已移除only_full_group_by
即使Laravel的strict设置为false,可能Bluehost的主机有全局SQL模式覆盖,你可以手动指定SQL模式:
在config/database.php的数据库连接配置中,添加modes选项,移除ONLY_FULL_GROUP_BY:
'mysql' => [ // ... 其他配置 'strict' => false, 'modes' => [ 'STRICT_TRANS_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'ERROR_FOR_DIVISION_BY_ZERO', 'NO_ENGINE_SUBSTITUTION', ], ],
修改后记得清除配置缓存:
php artisan config:clear
3. 优化参数绑定(避免SQL注入风险)
你原来的代码直接把变量拼接到SQL语句中,存在SQL注入风险,建议使用havingRaw的参数绑定方式(如上面解决方案1中的写法),把变量作为第二个参数传入,Laravel会自动处理绑定。
验证方法
先在phpMyAdmin中运行调整后的子查询,确认能正常执行:
SELECT employee_id FROM work_experiences WHERE employee_id = [某个员工ID] GROUP BY employee_id HAVING FLOOR(DATEDIFF(MAX(to_date), MIN(from_date))/365) >=10 AND FLOOR(DATEDIFF(MAX(to_date), MIN(from_date))/365) <=100
如果能正常返回结果,再把对应的逻辑写到Laravel查询构建器中,应该就能解决问题了。
内容的提问来源于stack exchange,提问作者kirushan

