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

Laravel9 Eloquent orderBy子查询报错 按用户取2条关联Post

实现方案

你遇到的两个问题都是对Eloquent对应能力的逻辑边界理解偏差导致的,直接按下面的步骤实现即可,全程仅产生3条SQL查询,完全无N+1问题。

问题根因说明

  • 排序场景使用的子查询属于SQL标量子查询,本身要求必须返回1行1列的单个值作为排序权重,所以保留limit(1)是完全正确的,这个子查询的作用只是取每个用户最新已发布Post的更新时间用来排序,和你需要预加载2条Post的需求没有关联,不需要修改这个子查询的limit配置,之前的1242报错就是因为子查询返回多行违反了标量子查询的规则。
  • 原生with()预加载闭包中添加的take()是对整个关联查询的结果集做全局条数限制,不会自动按外键(user_id)分组为每个父模型单独限制条数,所以才会出现总共只返回2条Post的问题。

可直接运行的代码

第一步:先在User模型中定义复用的已发布Post关联

// app/Models/User.php
public function publishedPosts()
{
    return $this->hasMany(Post::class)
        ->where('state', PostStateEnum::PUBLISHED)
        ->latest('updated_at');
}

第二步:业务查询逻辑

// 第1条SQL:按规则取排序后前4个用户的ID
$userIds = User::query()
    ->whereHas('publishedPosts')
    ->orderByDesc(
        Post::select('updated_at')
            ->where('state', PostStateEnum::PUBLISHED)
            ->whereColumn('user_id', 'users.id')
            ->latest('updated_at')
            ->limit(1)
    )
    ->take(4)
    ->pluck('id');

// 第2条SQL:查询4个目标用户的基础信息,保持排序顺序
$users = User::whereIn('id', $userIds)
    ->orderByRaw("FIELD(id, " . $userIds->join(',') . ")")
    ->get();

// 第3条SQL:一次性查询所有用户对应的最新2条已发布Post
$posts = Post::query()
    ->whereIn('user_id', $userIds)
    ->where('state', PostStateEnum::PUBLISHED)
    ->latest('updated_at')
    ->whereRaw('
        (SELECT COUNT(*) FROM posts AS sub_p
        WHERE sub_p.user_id = posts.user_id
        AND sub_p.state = ?
        AND sub_p.updated_at >= posts.updated_at) <= 2
    ', [PostStateEnum::PUBLISHED])
    ->get();

// 手动将Post挂载到User模型,无额外查询
$users->each(fn ($user) => 
    $user->setRelation('posts', $posts->where('user_id', $user->id)->values())
);

逻辑说明

  • 全程仅3次数据库查询,没有循环查库的N+1问题,性能和原生with预加载一致。
  • Post查询中的相关子查询会自动按用户分组,只返回每个用户最新的2条已发布Post,不会拉取冗余数据。
  • 用setRelation手动挂载关联的方式,和原生with预加载的结果结构完全一致,前端/接口层不需要做任何适配。
  • 如果你的数据库版本支持MySQL 8.0+ / PostgreSQL,也可以把Post查询里的相关子查询替换为窗口函数ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY updated_at DESC)做行号过滤,大表场景下性能会更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:19:06