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

在Laravel ORM中能否基于多列字段实现查询结果去重?

问题解答

distinct()失效原因

Laravel的distinct()方法不接受字段列表作为参数,该方法仅会对查询时SELECT的所有字段整体做去重判断。由于你查询的重复条目包含不同的id、created_at、updated_at值,SELECT全字段的场景下distinct自然不会判定为重复条目,因此达不到预期去重效果。

该需求完全可以仅通过SQL实现,以下是两种常用实现方案:

方案1:窗口函数方案(支持MySQL 8.0+/PostgreSQL/SQLite 3.25+版本)

核心逻辑是按6个discipline字段分区,每个分区内按更新时间倒序排序,取每个分区排序第一的条目即为最新的无重复数据。
原生SQL示例:

SELECT * FROM (
    SELECT *,
        ROW_NUMBER() OVER (
            PARTITION BY discipline_one, discipline_two, discipline_three, discipline_four, discipline_five, discipline_six
            ORDER BY updated_at DESC, id DESC
        ) AS rn
    FROM result_saves
    WHERE username = ?
) t WHERE rn = 1

对应的Laravel ORM实现:

$waybackWhen = \App\Models\ResultSave::query()
    ->selectRaw('*, ROW_NUMBER() OVER (PARTITION BY discipline_one, discipline_two, discipline_three, discipline_four, discipline_five, discipline_six ORDER BY updated_at DESC, id DESC) as rn')
    ->where('username', $result->username)
    ->having('rn', '=', 1)
    ->get();

方案2:低版本数据库兼容方案

如果数据库版本不支持窗口函数,可以用分组取最新值关联的方式实现:
原生SQL示例:

SELECT r.* FROM result_saves r
INNER JOIN (
    SELECT 
        discipline_one, discipline_two, discipline_three, discipline_four, discipline_five, discipline_six,
        MAX(updated_at) as latest_updated, MAX(id) as latest_id
    FROM result_saves
    WHERE username = ?
    GROUP BY discipline_one, discipline_two, discipline_three, discipline_four, discipline_five, discipline_six
) t ON 
    r.discipline_one = t.discipline_one
    AND r.discipline_two = t.discipline_two
    AND r.discipline_three = t.discipline_three
    AND r.discipline_four = t.discipline_four
    AND r.discipline_five = t.discipline_five
    AND r.discipline_six = t.discipline_six
    AND r.updated_at = t.latest_updated
    AND r.id = t.latest_id
WHERE r.username = ?

对应的Laravel ORM实现:

$subquery = \App\Models\ResultSave::query()
    ->selectRaw('discipline_one, discipline_two, discipline_three, discipline_four, discipline_five, discipline_six, MAX(updated_at) as latest_updated, MAX(id) as latest_id')
    ->where('username', $result->username)
    ->groupBy('discipline_one', 'discipline_two', 'discipline_three', 'discipline_four', 'discipline_five', 'discipline_six');

$waybackWhen = \App\Models\ResultSave::query()
    ->joinSub($subquery, 't', function ($join) {
        $join->on('result_saves.discipline_one', '=', 't.discipline_one')
            ->on('result_saves.discipline_two', '=', 't.discipline_two')
            ->on('result_saves.discipline_three', '=', 't.discipline_three')
            ->on('result_saves.discipline_four', '=', 't.discipline_four')
            ->on('result_saves.discipline_five', '=', 't.discipline_five')
            ->on('result_saves.discipline_six', '=', 't.discipline_six')
            ->on('result_saves.updated_at', '=', 't.latest_updated')
            ->on('result_saves.id', '=', 't.latest_id');
    })
    ->where('result_saves.username', $result->username)
    ->get('result_saves.*');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 21:06:06