Как я могу получить среднее значение отношений, а затем заказать по нему в Laravel 7.x? - PullRequest
0 голосов
/ 11 июля 2020

У меня есть таблица с именем students и таблица с именем scores.

Первичный ключ таблицы students - id. Таблица scores имеет внешний ключ от student_id до students.id Таблица scores также имеет много полей, два из которых - score и year, указывающие значение балла и год, в котором студент получил этот балл.

За год студент набрал много баллов. Я хочу получить их средний балл и ранжировать средний балл студентов в конкретном c году.

Модель «Студент» имеет отношение:


    class Student extends Model
    {
        public function scores()
        {
            return $this->hasMany('App\Score');
        }
    }

Я пробовал : В модели ученика


    class Student extends Model
    {
        public function average_score()
        {
            return $this->scores()
                ->selectRaw('avg(score) as score, student_id')
                ->groupBy('student_id');
        }
    }

В StudentCtrl,


    // Select only the student’s scores in a specific year
    $yearQuery = function($query) use ($request) {
        return $query->where('year', '=', $request->year);
    };
    
    $list = Student::select('id', 'name')
                     ->with(['average_score' => $yearQuery])
                     ->orderBy('average_score') // <-- If I delete this it works
                     ->paginate(15);

Ошибка: SQLSTATE [42S22]: Столбец не найден: 1054 Неизвестный столбец 'average_score' в 'предложении порядка'

1 Ответ

0 голосов
/ 12 июля 2020

Здесь мы собираемся использовать map () , groupBy () , avg () , sortBy ()

$response = []; // we'll store our final response here

$students = Student::select('id', 'name')->with('scores')->limit(15)->get();

$students->map(function ($student) {
    
    // groupBy student's each score by year
    return $student->scores->groupBy('year')->map(function ($score, $year) use ($student) {
        
       // create new array for simplicity
        $score = [
            'student_id' => $student->id,
            'student_name' => $student->name,
            'average_score' => $score->avg('score'),
            'year' => $year,
        ];
        return $score;

    })->toArray();
})->map(function($lists) use(&$response) {
    
    // groupBy students with each year
    collect($lists)->each(function($list) use(&$response){
        $response[$list['year']][] = collect($list)->forget('year')->toArray();
    });

})->toArray();

dd(collect($response)->map(function($list){
    return collect($list)->sortBy('average_score')->all(); // you sort here
})->all());

образец ответ

array:3 [
  2016 => array:2 [
    1 => array:3 [
      "student_id" => 2
      "student_name" => "Adam"
      "average_score" => 30
    ]
    0 => array:3 [
      "student_id" => 1
      "student_name" => "John"
      "average_score" => 37.5
    ]
  ]
  2017 => array:3 [
    1 => array:3 [
      "student_id" => 2
      "student_name" => "Adam"
      "average_score" => 50
    ]
    0 => array:3 [
      "student_id" => 1
      "student_name" => "John"
      "average_score" => 70
    ]
    2 => array:3 [
      "student_id" => 3
      "student_name" => "Tony"
      "average_score" => 80
    ]
  ]
  2018 => array:1 [
    0 => array:3 [
      "student_id" => 3
      "student_name" => "Tony"
      "average_score" => 100
    ]
  ]
]

Держите меня в курсе в комментариях ниже. Ура!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...