Laravel 加入以检索总计数

Laravel Joins to retrieve total count

我一直在尝试通过文档和多次尝试来解决这个问题,但我无法解决这个非常简单的问题。我正在使用 Laravel 7.

我有 3 个 table。

模型之间的关系设置为 Training hasMany Episodes。我的完成 table 有 user_id, episode_id 因为它是一个多对多的关系来显示用户观看了哪一集。

培训 table : id, title, description

剧集 table:id、标题、episode_number、描述、video_url、training_id (foreign_key)

完成数 table:id,user_id,episode_id

在我的索引视图中,我每次训练都会进行一次,我想显示有多少用户至少观看了 1 集。我尝试 eager-load 集 table 的培训,然后我想加入完成 table,然后我想 GROUP BY user_id 并计算它们,但它没有'根本不起作用...请帮忙? :)

我试过的代码:

$trainings = Training::with('user')->with(['episodes' => function ($query) {
    $query->join('completions', 'episodes.id', '=', 'completions.episode_id')
        ->join('users', 'completions.user_id', '=', 'users.id')
        ->select('completions.*, episodes.*', DB::raw('COUNT(completions.user_id) as totalctn'))
        ->groupBy('completions.user_id');
    }])->latest()->get();

非常感谢阅读/帮助我!

而不是

DB::raw('some query here')

试试这个:

$trainings = Training::with('user')->with(['episodes' => function ($query) {
    $query->join('completions', 'episodes.id', '=', 'completions.episode_id')
        ->join('users', 'completions.user_id', '=', 'users.id')
        ->select('completions.*, episodes.*')
        ->groupBy('completions.user_id')
        ->select([DB::raw('COUNT(completions.user_id) as totalctn'),'some','column','you','need']);
    }])->latest()->get();

更新 2

开始训练的用户总数(训练中有 1 集或多集)。 像这样的东西在 mysql 我想,请尝试。

$userCount = User::select(DB::raw('count(distinct(user_id))'))
 ->join('completions', 'completions.user_id', 'users.id')
 ->join('episodes', 'completions.episode_id', 'episodes.id')
 ->whereColumn('trainings.id', 'episodes.training_id')
 ->toSql(); //get the raw sql to use below

$trainings = Training::with('episodes')
    ->select('trainings.*', 
      DB::raw( "($userCount) as user_count"  ) //insert above sql. take note of the parentheses, it's important since it's actually enclosing the entire sql statement from above
     )
    ->get();

Laravel实际上在withCount方法后面使用了类似的方法。 这里发生了什么:

  • ->select('trainings.*', 这是一个正常的 select 要求 select 训练的所有列 table

  • DB::raw( "($userCount) as user_count" ) $userCount 会给我们 SQL 来计算完成 table 中出现的唯一 user_ids。此查询的最终结果将只是计数,因此我们将 subquery 作为名为 user_count 的列附加到 select 列表中。

    //in case the subquery needs a basic explanation.

  • $userCount查询:这里重要的条件是whereColumn中的条件。这就是使此查询附加到正在 select 的训练 table 中的每一行的原因。所以这个查询基本上转化为:对于训练 table 中的每一行,获取所有相关的剧集并计算唯一的用户 ID。这给出了在特定培训的完成列表中至少有一集的唯一用户数。


更新

For every training, I'd like to show how many users has watched at least 1 episode.

Training::with(['episodes' => function($query){
  return $query->withCount('users');
}])->get();

现在 Episode 关系将有一个名为 'users_count' 的属性,或者顺着这些词,指示观看该剧集的用户数量。


更新前

And my completions table has user_id, episode_id because it is a many to many relation to show which episode has been watched by users.

因此,可以安全地假设您的 User 模型具有一个 belongsToMany 关系方法,该方法通过完成 table 链接 User 和 Episode。类似于此:

public function completedEpisodes(){
 return $this->belongsToMany(Episode::class, 'completions_table');
}

I'd like to show how many users has watched at least 1 episode.

现在,您可以计算至少有一个 completedEpisode 的所有用户,如下所示:

User::has('completedEpisode')->count(); //use get() instead of count if you want to retrieve the results