有没有任何雄辩的方法来获得关系表的总和并按它排序?

时间:2018-05-11 23:17:10

标签: sql laravel collections eloquent laravel-5.6

示例:

表用户

ID | Username | sex
1  | Tony     | m
2  | Andy     | m
3  | Lucy     | f

表分数

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()
]);

希望我上面的例子有意义。我的代码确实有效,但我认为必须有一种雄辩而优雅的方式来做到这一点而没有foreach

2 个答案:

答案 0 :(得分:1)

以雄辩的方式执行此操作有两个选项。

选项1

第一种方法是将score_sum添加为查询users模型时始终包含的属性。如果您在查询score_sum表时大部分时间都使用users,那么这只是个好主意。如果您只需要非常具体的视图上的score_sum或特定的业务逻辑,那么我将使用下面的第二个选项。

要执行此操作,您需要将该属性添加到users模型,您可以在此处查看文档:{​​{3}}

以下是您的用例示例:

<强> /app/User.php

class User extends Model
{
    .
    .
    .
    public function getScoreSumAttribute($value)
    {
        return $this->scores()->sum('score');
    }
}

选项2

如果您只想针对单个用例执行此操作,那么最简单的解决方案就是在您将使用的最终sum()循环中使用foreach函数(最有可能在视图中) )。

例如在视图中:

@foreach($users as $user)
    <div>Username: {{$user->username}}</div>
    <div>Sex: {{$user->sex}}</div>
    <div>Score Sum: {{$user->scores()->sum('price')}}</div>
@endforeach

此外,如果您不想在foreach循环中执行此操作,则可以在Controller中的Eloquent调用中使用原始查询获取`score_sum&#39;。以下是如何做到这一点的示例:

$users = User::select('score_sum',DB::raw(SUM(score) FROM 'scores'))->get();

我没有快速的环境来测试它,你可能需要DB::raw查询中的WHERE子句

希望这有帮助!

答案 1 :(得分:1)

这很好:

User::selectRaw('*, (SELECT SUM(score) FROM scores WHERE user_id = users.id) as score_sum')
    ->orderBy('score_sum', 'DESC')
    ->get();