Laravel 加入以检索总数
Posted
技术标签:
【中文标题】Laravel 加入以检索总数【英文标题】:Laravel Joins to retrieve total count 【发布时间】:2020-12-15 17:59:26 【问题描述】:我一直试图通过文档和多次尝试来解决这个问题,但我无法解决这个非常简单的问题。我正在使用 Laravel 7。
我有 3 张桌子。
模型之间的关系设置为 Training hasMany Episodes。我的完成表有 user_id、episode_id,因为它是多对多关系,可以显示用户观看了哪一集。
培训表:id、标题、描述
剧集表:id、title、episode_number、description、video_url、training_id (foreign_key)
完成表:id、user_id、episode_id
在我的索引视图中,我对每次培训都进行了分析,并且我想显示有多少用户观看了至少 1 集。我试图急切加载培训的情节表,然后我想加入完成表,然后我想按 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();
非常感谢您阅读/帮助我!
【问题讨论】:
【参考方案1】:更新 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.*',
这是一个正常的选择,要求选择培训表的所有列
DB::raw( "($userCount) as user_count" )
$userCount
将给我们 SQL 来计算出现在完成表中的唯一 user_ids。此查询的最终结果将只是计数,因此我们将 subquery
作为名为 user_count
的列附加到选择列表中。
//in case the subquery needs a basic explanation.
$userCount
查询:这里的重要条件是whereColumn
中的条件。这就是使该查询附加到所选培训表中的每一行的原因。所以这个查询基本上翻译成:对于训练表中的每一行,获取所有相关的情节并计算唯一的用户 ID。这给出了在特定培训的完成列表中至少有一个情节的唯一用户的数量。
更新
对于每次培训,我想显示有多少用户观看了至少 1 集。
Training::with(['episodes' => function($query)
return $query->withCount('users');
])->get();
现在,Episode 关系将有一个名为“users_count”的属性,或者沿着这些词,表示观看过该剧集的用户数量。
更新前
我的完成表有 user_id、episode_id 因为它有很多 与许多关系显示用户观看了哪一集。
因此,可以安全地假设您的 User 模型具有通过完成表链接 User 和 Episodes 的 belongsToMany 关系方法。类似的东西:
public function completedEpisodes()
return $this->belongsToMany(Episode::class, 'completions_table');
我想显示有多少用户观看了至少 1 集。
现在,您可以计算至少有一个completedEpisode
的所有用户,如下所示:
User::has('completedEpisode')->count(); //use get() instead of count if you want to retrieve the results
【讨论】:
感谢您的回复!用户模型已经具有自定义 belongsToMany 的功能,我想从我急切加载的剧集中(来自培训)的剧集中获取按 user_id 分组的计数。我的查询总是失败...我认为这是一个简单的使用 count + groupBy 的连接查询,但不是... 所以本质上是获取用户已观看的剧集数?或者您想要用户观看与培训相关的视频的次数? Hmm.. 因此,您希望完成表计数中的不同用户用于培训。让我想想这个。我认为你应该做一个count(distinct(user_id))
实际上文档看起来是一个很好的起点:dev.mysql.com/doc/refman/8.0/en/subqueries.html 也检查一下:w3resource.com/mysql/subqueries/index.php 我将编辑答案以解释您提到的选择中发生了什么。
$sqlQuery = DB::raw("SELECT COUNT(DISTINCT(user_id)) FROM completions INNER JOIN episodes ON completions.episode_id = episodes.id WHERE trainings.id = episodes.training_id "); $trainings = Training::with('user') ->with('episodes') ->select('trainings.*', DB::raw("($sqlQuery) as participants")) ->latest() ->get();
因为我不需要用户表 :) 它工作得很好,非常感谢你,我从你那里学到了很多东西。和平【参考方案2】:
而不是
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();
【讨论】:
但我认为如果你静态调用Transaction::all()->with(...)->count()
,你可以使用count函数
好的伙计,非常感谢您的回复!但我想通过 with() 来计算我急切加载的剧集的数量。做一些像 $training->episodes->userCount;类似的东西。我会尽快尝试你的代码并保持联系:) 你认为这可能吗?
是的,我认为您有可能以这种方式完成 50%,但没有什么是不可能的 :) 您已经做出了加入并建立关系的好选择,但我认为选择和 COUNT as DB::raw 可以完成我认为的工作。以上是关于Laravel 加入以检索总数的主要内容,如果未能解决你的问题,请参考以下文章
Laravel Eloquent Eager Loading:加入同一张表两次