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

Laravel使用Eloquent join时如何从关联表按locale优先级仅取1条记录

问题原因

你原有代码的错误在于:leftJoin闭包内添加的limit(1)是对整个color_translations关联表做全局行数限制,而非按每个color_id分组后分别取优先级最高的1条翻译记录,关联时仍会匹配所有colors.id = color_translations.color_id的行,因此返回5条结果。

解决方案

推荐使用MySQL 8.0及以上支持的窗口函数ROW_NUMBER()实现分组取top1的需求,对应的Eloquent代码如下:

use Illuminate\Support\Facades\DB;

$this->colorsModel
    ->select([
        'colors.*',
        'ct.locale',
        'ct.title',
        'ct.url'
    ])
    ->leftJoinSub(
        // 子查询给每个color对应的翻译按优先级排序打编号
        DB::table('color_translations')
            ->selectRaw('*, ROW_NUMBER() OVER (PARTITION BY color_id ORDER BY FIELD(locale, "en", "fr", "de") ASC) as rn')
            ->having('rn', '=', 1),
        'ct',
        'colors.id',
        '=',
        'ct.color_id'
    )
    ->get();

兼容低版本MySQL的替代方案

如果你的MySQL版本不支持窗口函数,可以用相关子查询的写法:

use Illuminate\Support\Facades\DB;

$this->colorsModel
    ->select([
        'colors.*',
        'color_translations.locale',
        'color_translations.title',
        'color_translations.url'
    ])
    ->leftJoin('color_translations', 'colors.id', '=', 'color_translations.color_id')
    ->whereRaw(
        'color_translations.id = (
            SELECT id FROM color_translations 
            WHERE color_id = colors.id 
            ORDER BY FIELD(locale, "en", "fr", "de") ASC 
            LIMIT 1
        )'
    )
    ->get();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 23:09:04