Объедините whereRaw () с leftjoin (), используя красноречие - PullRequest
1 голос
/ 09 июля 2020

Я пытаюсь объединить 2 таблицы и получить последние уникальные результаты, используя whereRaw() и leftJoin() с Laravel красноречиво.

У меня есть 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| 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();

Может ли кто-нибудь помочь мне разобраться, что происходит не так?

EDIT: -

Оказывается, ошибка 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 голосов
/ 09 июля 2020

Я думаю, что есть небольшая проблема с вашим ожидаемым результатом (идентификатор и имя не совпадают), но я заставил его работать следующим образом:

Запрос;

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.*']);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...