我正在构建一个分数跟踪器,请查看问题how to track score gains in mysql以获取更多详细信息。
在这个问题中,我问如何从数据库中获取特定数据,我得到了一个很好的答案,可以返回正确的数据,但是现在我需要将其添加到laravel中。
我希望只使用whereRaw(),但这会引发很多错误,而且很可能不是最佳解决方案。
到目前为止,我已经在Player和SkillScores之间建立了hasMany关系
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;
编辑:-
我现在已经设法通过使用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");
}