Я создаю счетчик баллов, подробнее см. Вопрос как отслеживать прирост баллов в mysql.
В этом вопросе я спросил, как получить данные c данные из моей базы данных, я получил отличный ответ, который возвращает правильные данные, однако теперь мне нужно добавить это в laravel.
Я надеялся просто использовать whereRaw (), но это вызвало много ошибок, и, скорее всего, это не лучшее решение.
пока что я установил связь hasMany между Player и SkillScores
class Player extends Model
{
public function scores()
{
return $this->hasMany(SkillScores::class);
}
}
Я добавил черту scopeWithskills () для поиска имя навыка:
class SkillScores extends Model
{
public function scopeWithSkills(Builder $query)
{
$query->leftJoinSub(
'select * FROM skills',
'skills',
'skills.id',
'skill_scores.skill_id'
);
}
}
Я отправляю это в свое представление в PlayerController:
class PlayerController extends Controller
{
public function index()
{
return view('player', [
'players' => auth()->user()->players()
]);
}
public function show(Player $player)
{
return view('player.show', [
'player' => $player,
'scores' => $player->scores()->withSkills()->get()
]);
}
}
Какие еще отношения мне нужно настроить, чтобы выполнить запрос ниже?
WITH cte AS (
SELECT id, player_id, skill_id,
FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) score,
FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) - FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at ASC) gain,
ROW_NUMBER() OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) rn
FROM skill_scores
WHERE created_at BETWEEN @current_date - INTERVAL @interval DAY AND @current_date
)
SELECT cte.player_id, skills.name, cte.score, cte.gain
FROM cte
JOIN skills ON skills.id = cte.skill_id
WHERE rn = 1
ORDER BY player_id, name;
EDIT: -
Теперь мне удалось заставить это работать, используя DB::select()
вместо whereRaw()
, но не могу не думать, что должен быть лучший способ добиться этого с отношения: -
public function gains($interval = 1)
{
return DB::select("WITH cte AS (
SELECT id, player_id, skill_id,
FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) score,
FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) - FIRST_VALUE(score) OVER (PARTITION BY player_id, skill_id ORDER BY created_at ASC) gain,
ROW_NUMBER() OVER (PARTITION BY player_id, skill_id ORDER BY created_at DESC) rn
FROM skill_scores2
WHERE created_at BETWEEN now() - INTERVAL '$interval' DAY AND now() AND player_id = '$this->id'
)
SELECT cte.player_id, skills.name, cte.score, cte.gain
FROM cte
JOIN skills ON skills.id = cte.skill_id
WHERE rn = 1
ORDER BY player_id, name");
}