You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中含ROW_NUMBER() OVER PARTITION子查询报错原因咨询

问题根源与解决办法

我之前也碰到过几乎一模一样的问题,其实核心原因是MySQL的sql_mode配置在你的Sequel Pro连接和Laravel数据库连接中不一样:

  • 你的Sequel Pro连接没有启用ONLY_FULL_GROUP_BY这个严格模式规则,所以MySQL允许你这种包含窗口函数的子查询写法;
  • 但Laravel的数据库连接默认(或者你的配置里)开启了ONLY_FULL_GROUP_BY,MySQL的解析器会误把窗口函数里的PARTITION BY当成普通的GROUP BY操作,进而触发那个"混合分组列与非分组列"的错误——毕竟严格模式下要求分组查询必须明确GROUP BY所有非聚合列,但窗口函数的逻辑本来就不需要这个。

下面给你几个可行的解决思路:

1. 临时修改当前连接的sql_mode

在执行你的目标查询前,先通过Laravel执行一条语句移除ONLY_FULL_GROUP_BY:

// 先调整sql_mode
DB::statement("SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));");
// 再执行你的分页查询
$results = DB::select("select * from (select *, ROW_NUMBER() OVER(PARTITION BY type ORDER BY id) AS seqnum from `example`) as `t` where `seqnum` <= 50");

这种方式只会影响当前请求的数据库连接,不会全局修改配置。

2. 全局修改Laravel的数据库配置

如果你希望所有Laravel的数据库连接都禁用这个严格规则,可以修改config/database.php里的mysql配置项,添加modes数组并移除ONLY_FULL_GROUP_BY:

'mysql' => [
    // ... 其他已有的配置项
    'modes' => [
        'STRICT_TRANS_TABLES',
        'NO_ZERO_IN_DATE',
        'NO_ZERO_DATE',
        'ERROR_FOR_DIVISION_BY_ZERO',
        'NO_ENGINE_SUBSTITUTION',
    ],
],

修改完记得清除配置缓存:

php artisan config:clear

3. 优化查询写法(兼容严格模式)

有时候MySQL的解析器对select *的处理会有点迷糊,你可以尝试明确列出需要的列,代替select *,让解析器更清楚这是窗口函数操作而非普通分组:

select t.* from (
    select id, type, -- 这里换成你实际需要的列
           ROW_NUMBER() OVER(PARTITION BY type ORDER BY id) AS seqnum 
    from `example`
) as `t` where `t.seqnum` <= 50

这种写法也能避免解析器误判,同时让查询更清晰。


内容的提问来源于stack exchange,提问作者I am L

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 08:32:51