如何在Laravel中查询用户活动并统计用户文章阅读量分布
解决Laravel中用户阅读量分组统计的问题
刚好之前做过类似的需求,我来帮你梳理一下实现思路和具体的查询代码。
核心需求是统计「阅读N篇文章的用户数量」,这里需要注意两个关键点:一是要包含没有阅读任何文章的用户(也就是阅读0篇的情况),二是要区分「阅读记录数」和「阅读的不同文章数」(如果你的activities表有article_id字段的话)。
方法一:使用数据库查询构建器(推荐,性能更优)
这种方式直接在数据库层面完成分组统计,避免把大量数据加载到内存处理,适合用户量较大的场景。
步骤1:先统计每个用户的阅读文章数量
我们用leftJoin关联users和activities,确保没有阅读记录的用户也能被包含进来:
// 子查询:获取每个用户的阅读文章数量 $userReadCounts = DB::table('users') ->leftJoin('activities', function ($join) { $join->on('users.id', '=', 'activities.user_id') ->where('activities.read', '=', 1); // 只统计标记为已阅读的记录 // 如果你的activity字段有其他类型(比如点赞、评论),可以加上过滤: // ->where('activities.activity', '=', 'view'); }) ->select( 'users.id', // 如果你要统计「不同文章的数量」,把COUNT(activities.id)改成COUNT(DISTINCT activities.article_id) DB::raw('COUNT(activities.id) as total_read') ) ->groupBy('users.id');
步骤2:按阅读数量分组统计用户数
基于上面的子查询,我们再对「阅读数量」进行分组,统计每个数量对应的用户数:
$stats = DB::table($userReadCounts, 'user_reads') ->select( 'total_read as read_articles_count', DB::raw('COUNT(*) as user_number') ) ->groupBy('total_read') ->orderBy('total_read') // 按阅读数量升序排列 ->get();
最终$stats会返回类似这样的集合:
Illuminate\Support\Collection { all: [ {#1234 read_articles_count: 0, user_number: 45, }, {#1235 read_articles_count: 1, user_number: 28, }, {#1236 read_articles_count: 2, user_number: 15, }, // ...更多阅读数量分组 ], }
方法二:使用Eloquent关联(适合小数据量场景)
如果你的用户量不大,也可以用Eloquent的关联统计来实现,代码更简洁:
首先在User模型中定义关联:
// app/Models/User.php public function readActivities() { return $this->hasMany(Activity::class) ->where('read', 1) ->where('activity', 'view'); // 按需过滤活动类型 }
然后通过withCount获取每个用户的阅读数量,再在内存中分组:
$stats = User::withCount('readActivities') ->get() ->groupBy('read_activities_count') ->map(function ($usersGroup) { return $usersGroup->count(); }) ->sortKeys(); // 按阅读数量排序
这个方法的结果是一个键为阅读数量、值为用户数的集合,比如:
Illuminate\Support\Collection { all: [ 0 => 45, 1 => 28, 2 => 15, // ... ], }
注意事项
- 如果
activities表中存在同一用户多次阅读同一篇文章的记录,你需要用COUNT(DISTINCT activities.article_id)来统计不同文章的数量,而不是单纯的记录数。 - 确保
activities.user_id有索引,这样关联查询的性能会更好。
内容的提问来源于stack exchange,提问作者Steven Grant
相关产品推荐
相关产品推荐

