Laravel OrderBy OneToMany Relation
У меня есть 2 таблицы events_users: в которых хранится информация о людях, которые посетили определенные события. Многие люди посещают много событий, следовательно, используя эту таблицу ссылок.
+--------+---------+---------+
| eid | user_id | slot_no |
+--------+---------+---------+
| event1 | user1 | 0 |
| event1 | user2 | 1 |
| event2 | user3 | 0 |
+--------+---------+---------+
И events_user_score: который записывает разные оценки людей на мероприятиях. На разных мероприятиях может быть много разных типов очков, поэтому это в отдельной таблице, а не в столбцах первой таблицы.
+--------+---------+------------+--------+
| eid | user_id | score_type | number |
+--------+---------+------------+--------+
| event1 | user1 | 1 | 4 |
| event1 | user1 | 2 | 3 |
| event2 | user3 | 1 | 6 |
| event1 | user1 | 2 | 5 | <- this row could not exist as
+--------+---------+------------+--------+ no duplicates possible with same eid, user_id & score_type
Я хотел бы иметь возможность отсортировать выборку из первой таблицы на основе рисунков во второй таблице. Так что хотелось бы получить совместную работу, которая даст такой результат. По сути, превращение Score_type в столбцы с числом в качестве значения.
+--------+---------+---------+---+---+
| eid | user_id | slot_no | 1 | 2 |
+--------+---------+---------+---+---+
| event1 | user1 | 0 | 4 | 3 |
| event1 | user2 | 1 | | |
| event2 | user3 | 0 | 6 | |
+--------+---------+---------+---+---+
До сих пор я пытался использовать hasMany от laravel, но я не могу сортировать, используя эту технику. Итак, я пытаюсь попробовать левое соединение какого-то типа, но запуталось, потому что теперь я не получаю никаких очков назад:
$attendees = Events_user::whereIn("events_users.eid", $lastWeeksEvents->pluck('eid'))->where("slot_no",">=",0)
->leftJoin('event_user_score', function ($join) {
$join->on('events_users.eid', '=', 'event_user_score.eid')
->where('events_users.uid', '=', 'event_user_score.uid');
})
->get();
Предположим, что $lastWeeksEvents
возвращает список событий с EID, совпадающими с событиями в первой таблице.
Отредактируйте - хотя это и есть Score_types 1 - 6. Давайте попробуем получить типы 1 и 2 в виде столбцов. Если это облегчает?
2 ответа
Вы также можете использовать подзапрос следующим образом:
Простой SQL:
select u.eid, u.user_id, u.slot_no,
(select number from events_user_score s where s.eid = u.eid and s.user_id = u.user_id and s.score_type = 1) as `1`,
(select number from events_user_score s where s.eid = u.eid and s.user_id = u.user_id and s.score_type = 2) as `2`
from events_users u
Теперь, используя это в Laravel:
//Get all score types
$score_types = DB::table('events_user_score')
->select('score_type')
->groupBy('score_type')
->get();
$event_query = Events_user::from(DB::raw('events_users u'))
->select('eid', 'user_id', 'slot_no');
//Add score types as sub queries
foreach ($score_types as $score) {
$event_query->addSelect(DB::raw('(select number from events_user_score s where s.eid = u.eid and s.user_id = u.user_id and s.score_type = ' . $score->score_type . ') as `' . $score->score_type . '`'));
}
//Example, to sort by score type 1
$data = $event_query->orderBy('1')->get();
Не забудьте добавить use DB;
в верхней части вашего кода.
Чтобы получить желаемые результаты, вы можете написать следующее в простом SQL как
select e1.*,
max(case when e2.score_type =1 then e2.number else 0 end ) score_type1,
max(case when e2.score_type =2 then e2.number else 0 end ) score_type2
from events_users e1
left join events_user_score e2 on e1.eid = e2.eid
and e1.user_id = e2.user_id
group by e1.eid, e1.user_id,e1.slot_no
Приведенный выше запрос предполагает, что в качестве 1 и 2 могут быть два параметра Score_types, если их больше, приведенный выше запрос не будет выполним для такого типа набора результатов.
То же самое, используя конструктор запросов laravel, можно записать как.
$attendees = Events_user::from('events_users as e1')
->select(DB::raw("e1.*,max(case when e2.score_type =1 then e2.number else 0 end ) score_type1, max(case when e2.score_type =2 then e2.number else 0 end ) score_type2"))
->leftJoin('events_user_score as e2', function ($join) {
$join->on('e1.user_id', '=', 'e2.user_id');
})
->groupBy('e1.eid')
->groupBy('e1.user_id')
->groupBy('e1.slot_no')
->get();
Вышеупомянутое решение присоединиться events_users
стол со вторым столом events_user_score
сопоставляя событие и пользователя. Агрегация вызывается для получения уникальных данных для eid, user_id & slot_no