Есть ли какой-нибудь красноречивый способ получить сумму реляционной таблицы и отсортировать по ней? - PullRequest
0 голосов
/ 12 мая 2018

Пример:

Таблица пользователей

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

Код, который я использую такfar:

Модель пользователя:

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 голосов
/ 12 мая 2018

Это так хорошо, как получается:

User::selectRaw('*, (SELECT SUM(score) FROM scores WHERE user_id = users.id) as score_sum')
    ->orderBy('score_sum', 'DESC')
    ->get();
0 голосов
/ 12 мая 2018

Есть 2 варианта для красноречивого выполнения.

Вариант 1

Первый способ - добавить score_sum в качестве атрибута, который всегда включается при запросе модели users. Это только хорошая идея, если вы будете использовать score_sum большую часть времени при запросе таблицы users. Если вам нужен только score_sum для очень специфического представления или для конкретной бизнес-логики, тогда я бы использовал второй вариант ниже.

Для этого вы добавите атрибут к модели users, вы можете посмотреть здесь документацию: https://laravel.com/docs/5.6/eloquent-mutators#defining-an-accessor

Вот пример вашего варианта использования:

/ приложение / 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, вы можете использовать необработанный запрос при вызове Eloquent в вашем контроллере, который получает `score_sum '. Вот пример того, как это можно сделать:

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

У меня не было быстрой среды для проверки этого, вам может понадобиться предложение WHERE в запросе DB::raw

Надеюсь, это поможет!

...