雄辩地将whereRaw()与leftjoin()结合起来

时间:2020-07-08 22:50:51

标签: php mysql laravel eloquent

我正在尝试使用whereRaw()leftJoin()和Laravel雄辩地加入2个表并获得最新的唯一结果。

我有2张桌子:-

技能表(带有时间戳):-

| id|   name  |  icon      |
| 1 | skill 1 | skill1.png |
| 2 | skill 2 | skill2.png |
| 3 | skill 3 | skill3.png |

得分表(带有时间戳):-

| id| player_id | skill_id | score |
| 1 | 1         | 1        | 1     |
| 2 | 1         | 2        | 1     |
| 3 | 1         | 3        | 1     |
| 4 | 1         | 2        | 2     |

我想返回所有技能,但仅返回最新条目(按ID),因此对于上面的代码段,我应该得到:-

| id| player_id | name    | skill_id | score |
| 1 | 1         | skill 1 | 1        | 1     |
| 3 | 1         | skill 3 | 1        | 1     |
| 4 | 1         | skill 2 | 2        | 2     |

我可以使用以下方法获取最新的唯一记录:

return SkillScores::where('player_id', $this->id)
        ->whereRaw('id in (select max(id) from skills group by (name))')
        ->get();

我可以通过以下方式获得技能名称:-

return SkillScores::where('player_id', $this->id)
        ->leftJoin('skills', 'skill_scores.skill_id', '=', 'skills.id')
        ->get();

但是当我将它们结合在一起时,会出现SQLSTATE [23000]错误

return SkillScores::where('player_id', $this->id)
        ->whereRaw('id in (select max(id) from skills group by (name))')
        ->leftJoin('skills', 'skill_scores.skill_id', '=', 'skills.id')
        ->get();

谁能帮我找出问题所在?

编辑:-

事实证明,发生SQLSTATE [23000]错误是因为我在两个表中都有一个id列,但我没有告诉它我所引用的是哪一个,以下内容解决了该问题并给出了正确的结果。 >

return SkillScores::where('player_id', $this->id)
        ->whereRaw('skill_scores.id in (select max(skill_scores.id) from skill_scores group by (skill_id))')
        ->leftJoin('skills', 'skill_scores.skill_id', '=', 'skills.id')
        ->get();

1 个答案:

答案 0 :(得分:-1)

我认为您的预期结果存在一个小问题(id和名称不匹配),但我按以下方式进行了工作;

查询;

SELECT scores.*, skills.*
FROM scores
         INNER JOIN (SELECT skill_id, max(id) AS maxId
                     FROM scores
                     WHERE player_id = 1
                     GROUP BY skill_id) AS sub ON sub.maxId = scores.id
         INNER JOIN skills ON skills.id = scores.skill_id;

雄辩的版本(如果需要,可以用DB::table()代替)

$subQuery = Score::where('player_id', DB::raw($this->id))
   ->groupBy('skill_id')
   ->select('skill_id', DB::raw('MAX(id) as maxId'));

return Score::join(DB::raw('(' . $subQuery->toSql() . ') as subQuery'), 'subQuery.maxId', '=', 'scores.id')
    ->join('skills', 'skills.id', '=', 'scores.skill_id')
    ->get(['scores.*', 'skills.*']);