本文目录导读:

在 Laravel 中进行关联查询的排序和分组,有多种方法,以下是常用的几种方式:
关联查询排序
使用 orderBy 在关联查询中
// 一对多关联 - 根据关联表字段排序
$posts = Post::with(['comments' => function($query) {
$query->orderBy('created_at', 'desc');
}])->get();
// 根据关联表字段对主表排序
$posts = Post::with('user')
->join('users', 'posts.user_id', '=', 'users.id')
->orderBy('users.name', 'asc')
->select('posts.*')
->get();
使用 orderByRelation 方法
// 根据关联表的某个字段排序(Laravel 8.0+)
$posts = Post::orderBy('user.name')->get();
// 或者使用子查询
$posts = Post::orderByDesc(
User::select('name')->whereColumn('users.id', 'posts.user_id')
)->get();
关联查询分组
使用 groupBy 在关联查询中
// 按关联关系分组统计
$categories = Category::with(['posts' => function($query) {
$query->select('category_id', DB::raw('count(*) as post_count'))
->groupBy('category_id');
}])->get();
// 使用 withCount 统计关联数量
$categories = Category::withCount('posts')->get();
复杂场景示例
排序 + 分组 + 统计
// 查询每个分类下的文章数量,并按数量排序
$categories = Category::withCount('posts')
->having('posts_count', '>', 0)
->orderBy('posts_count', 'desc')
->get();
// 关联查询+条件+排序
$users = User::with(['orders' => function($query) {
$query->where('status', 'completed')
->orderBy('created_at', 'desc')
->limit(5);
}])->get();
// 多表关联分组统计
$products = Product::with(['orders' => function($query) {
$query->select('product_id', DB::raw('SUM(quantity) as total_quantity'))
->groupBy('product_id');
}])->get();
高级用法
使用 groupBy + orderBy 组合
// 按年份分组查询文章,并按年份排序
$postsByYear = Post::select('year', DB::raw('count(*) as total'))
->groupBy('year')
->orderBy('year', 'desc')
->get();
// 关联查询中的子查询排序(最有效的方法之一)
$users = User::select('users.*')
->addSelect(['latest_post_title' => Post::select('title')
->whereColumn('user_id', 'users.id')
->orderBy('created_at', 'desc')
->limit(1)
])
->get();
使用查询构建器
// 使用查询构建器进行复杂的关联分组
$results = DB::table('users')
->join('posts', 'posts.user_id', '=', 'users.id')
->select('users.id', 'users.name', DB::raw('COUNT(posts.id) as post_count'))
->groupBy('users.id', 'users.name')
->orderBy('post_count', 'desc')
->get();
注意事项
- 性能优化:使用
withCount比手动分组统计性能更好 - 索引优化:分组和排序的字段建议添加索引
- 缓存结果:频繁使用的查询可以缓存结果
- 索引优化:对于频繁的排序和分组字段,添加合适的索引
// 缓存查询结果
$cachedPosts = Cache::remember('posts_with_comments', 3600, function() {
return Post::with('comments')
->orderBy('created_at', 'desc')
->get();
});
选择哪种方法取决于你的具体需求,简单的场景用 with + orderBy,复杂统计用 withCount 或查询构建器。