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

不使用GROUP BY、UNIQUE或DISTINCT,如何在Laravel中实现数据分组?

Laravel分组查询替代方案(避免关闭strict模式)

关于strict模式的疑问

你并没有多虑:Laravel数据库配置中的strict模式包含only_full_group_by规则,这是符合SQL标准的约束,目的是避免分组查询返回不确定的结果(比如随机选取未分组字段的值)。保持strict模式开启能减少潜在的逻辑bug,不建议关闭。

替代方案

你的需求是按company_agreement_id分组,同时获取对应记录的id,这里需要明确:每个company_agreement_id对应多条记录时,你需要哪一条的id?以下是两种常见场景的实现方式:

场景1:取每个分组下最新的id(按id倒序取第一条)

使用窗口函数ROW_NUMBER()可以精准控制选取分组内的指定记录,符合SQL标准且无需关闭strict模式:

原生SQL写法

SELECT id, company_agreement_id
FROM (
    SELECT 
        id, 
        company_agreement_id,
        ROW_NUMBER() OVER (PARTITION BY company_agreement_id ORDER BY id DESC) AS rn
    FROM company_agreement_historicals
    WHERE ((expiration_date > ? and status = ?) or status = ?)
) AS sub
WHERE rn = 1;

Laravel Query Builder写法

$test = DB::table('company_agreement_historicals')
    ->select('id', 'company_agreement_id')
    ->fromSub(function ($query) {
        $query->select(
            'id',
            'company_agreement_id',
            DB::raw('ROW_NUMBER() OVER (PARTITION BY company_agreement_id ORDER BY id DESC) AS rn')
        )->where(function ($q) {
            $q->where('expiration_date', '>', '2023-09-04 11:19:05')
              ->where('status', 2);
        })->orWhere('status', 1);
    }, 'sub')
    ->where('rn', 1)
    ->get();

场景2:取每个分组下最小的id(或最大id)

如果只需要分组内的最小/最大id,可以直接用聚合函数配合GROUP BY,这也是符合SQL标准的写法:

原生SQL写法

SELECT MIN(id) AS id, company_agreement_id
FROM company_agreement_historicals
WHERE ((expiration_date > ? and status = ?) or status = ?)
GROUP BY company_agreement_id;

Laravel Query Builder写法

$test = DB::table('company_agreement_historicals')
    ->select(DB::raw('MIN(id) AS id'), 'company_agreement_id')
    ->where(function ($q) {
        $q->where('expiration_date', '>', '2023-09-04 11:19:05')
          ->where('status', 2);
    })
    ->orWhere('status', 1)
    ->groupBy('company_agreement_id')
    ->get();

为什么原SQL有问题

原SQL在开启only_full_group_by时会报错,因为SELECT中的id字段既不在GROUP BY列表中,也没有使用聚合函数,数据库无法确定应该返回分组内哪一条记录的id,返回结果是不确定的。严格模式下禁止这种写法,正是为了避免这种逻辑模糊的问题。

内容的提问来源于stack exchange,提问作者Alexander

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 01:02:32