MySQL查询雄辩

时间:2020-07-13 12:46:59

标签: mysql laravel eloquent

我正在构建一个分数跟踪器,请查看问题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");
}

0 个答案:

没有答案