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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 20:07:29