是否有任何 Eloquent 方法来获取关系 table 的总和并对其进行排序?
Is there any Eloquent way to get sum of relational table and sort by it?
示例:
table 用户
ID | Username | sex
1 | Tony | m
2 | Andy | m
3 | Lucy | f
table 分数
ID | user_id | score
1 | 2 | 4
2 | 1 | 3
3 | 1 | 4
4 | 2 | 3
5 | 1 | 1
6 | 3 | 3
7 | 3 | 2
8 | 2 | 3
预期结果:
ID | Username | sex | score_sum (sum) (desc)
2 | Andy | m | 10
1 | Tony | m | 8
3 | Lucy | f | 5
我目前使用的代码:
用户模型:
class User extends Authenticatable
{
...
public function scores()
{
return $this->hasMany('App\Score');
}
...
}
评分模型
class Job extends Model
{
//i put nothing here
}
控制器中的代码:
$users = User::all();
foreach ($users as $user){
$user->score_sum = $user->scores()->sum('score');
}
$users = collect($users)->sortByDesc('score_sum');
return view('homepage', [
'users' => $users->values()->all()
]);
希望我上面的例子有意义。我的代码确实有效,但我认为必须有一种 Eloquent 和优雅的方式来做到这一点,而不需要 foreach
?
Eloquent 有两种选择。
选项 1
第一种方法是将 score_sum
添加为查询 users
模型时始终包含的属性。如果您在查询 users
table 时大部分时间都使用 score_sum
,那么这只是一个好主意。如果您只需要在非常特定的视图或特定的业务逻辑上使用 score_sum
,那么我会使用下面的第二个选项。
为此,您需要将属性添加到 users
模型,您可以在此处查看文档:https://laravel.com/docs/5.6/eloquent-mutators#defining-an-accessor
这是您的用例示例:
/app/User.php
class User extends Model
{
.
.
.
public function getScoreSumAttribute($value)
{
return $this->scores()->sum('score');
}
}
选项 2
如果您只想针对单个用例执行此操作,那么最简单的解决方案就是在您将要使用的最终 foreach
循环中使用 sum()
函数(很可能在风景)。
例如在视图中:
@foreach($users as $user)
<div>Username: {{$user->username}}</div>
<div>Sex: {{$user->sex}}</div>
<div>Score Sum: {{$user->scores()->sum('price')}}</div>
@endforeach
此外,如果您不想在 foreach
循环中执行此操作,您可以在控制器中的 Eloquent 调用中使用原始查询获取“score_sum”。这是一个如何做到这一点的例子:
$users = User::select('score_sum',DB::raw(SUM(score) FROM 'scores'))->get();
我没有快速环境来测试它,您可能需要在 DB::raw
查询中使用 WHERE 子句
希望对您有所帮助!
这真是太棒了:
User::selectRaw('*, (SELECT SUM(score) FROM scores WHERE user_id = users.id) as score_sum')
->orderBy('score_sum', 'DESC')
->get();
示例:
table 用户
ID | Username | sex
1 | Tony | m
2 | Andy | m
3 | Lucy | f
table 分数
ID | user_id | score
1 | 2 | 4
2 | 1 | 3
3 | 1 | 4
4 | 2 | 3
5 | 1 | 1
6 | 3 | 3
7 | 3 | 2
8 | 2 | 3
预期结果:
ID | Username | sex | score_sum (sum) (desc)
2 | Andy | m | 10
1 | Tony | m | 8
3 | Lucy | f | 5
我目前使用的代码:
用户模型:
class User extends Authenticatable
{
...
public function scores()
{
return $this->hasMany('App\Score');
}
...
}
评分模型
class Job extends Model
{
//i put nothing here
}
控制器中的代码:
$users = User::all();
foreach ($users as $user){
$user->score_sum = $user->scores()->sum('score');
}
$users = collect($users)->sortByDesc('score_sum');
return view('homepage', [
'users' => $users->values()->all()
]);
希望我上面的例子有意义。我的代码确实有效,但我认为必须有一种 Eloquent 和优雅的方式来做到这一点,而不需要 foreach
?
Eloquent 有两种选择。
选项 1
第一种方法是将 score_sum
添加为查询 users
模型时始终包含的属性。如果您在查询 users
table 时大部分时间都使用 score_sum
,那么这只是一个好主意。如果您只需要在非常特定的视图或特定的业务逻辑上使用 score_sum
,那么我会使用下面的第二个选项。
为此,您需要将属性添加到 users
模型,您可以在此处查看文档:https://laravel.com/docs/5.6/eloquent-mutators#defining-an-accessor
这是您的用例示例:
/app/User.php
class User extends Model
{
.
.
.
public function getScoreSumAttribute($value)
{
return $this->scores()->sum('score');
}
}
选项 2
如果您只想针对单个用例执行此操作,那么最简单的解决方案就是在您将要使用的最终 foreach
循环中使用 sum()
函数(很可能在风景)。
例如在视图中:
@foreach($users as $user)
<div>Username: {{$user->username}}</div>
<div>Sex: {{$user->sex}}</div>
<div>Score Sum: {{$user->scores()->sum('price')}}</div>
@endforeach
此外,如果您不想在 foreach
循环中执行此操作,您可以在控制器中的 Eloquent 调用中使用原始查询获取“score_sum”。这是一个如何做到这一点的例子:
$users = User::select('score_sum',DB::raw(SUM(score) FROM 'scores'))->get();
我没有快速环境来测试它,您可能需要在 DB::raw
查询中使用 WHERE 子句
希望对您有所帮助!
这真是太棒了:
User::selectRaw('*, (SELECT SUM(score) FROM scores WHERE user_id = users.id) as score_sum')
->orderBy('score_sum', 'DESC')
->get();