Проблем объединения нескольких таблиц
При работе с БД часто возникает ситуация, когда надо вывести данные сразу из нескольких таблиц.
Возьмем любую строчку из таблицы schedule_items
SELECT *
FROM schedule_items
WHERE id = 6204102
увидим что-то такое
посмотрим на поле teacher_id, там значение 4520
. Мы уже знаем, что по этому полю можно сходить в таблицу teachers и найти там, кто есть этот 4520
SELECT *
FROM teachers
WHERE id = 4520;
и было, наверное, здорово, если бы могли вместо цифры подставить ФИО преподавателя.
К сожалению, в БД, нет простого решения этой проблемы.
Но есть универсальный подход, построенный на так называемой склейке (объединении) таблиц.
Склейка таблиц через JOIN
Схема такая, берется основная таблица. Допустим возьмем расписание этого 4520
, оставим поменьше столбцов чтобы не путаться:
SELECT id, groups, discipline, ngroup, group_id, teacher_id
FROM schedule_items
WHERE teacher_id = 4520 and dbeg = '2023-03-06';
а теперь нам надо каждой строчке из основной таблицы сопоставить строчку из дополнительной.
То есть на каждую строчку из основой, мы сопоставляем копию из второстепенной таблицы. Как-то так:
сопоставляем обязательно должно быть по какому-то признаку. В нашем случае это совпадение teacher_id
из основной таблицы с id
из второстепенной
С точки зрения sql
, пишется вот так:
SELECT *
FROM schedule_items
JOIN teachers ON schedule_items.teacher_id = teachers.id
WHERE teacher_id = 4520 and dbeg = '2023-03-06';
получим такое в ответ
Как вывести столбцы с одинаковыми названиями
попробуем теперь оставить только нужные столбцы:
SELECT id, groups, discipline, ngroup, group_id, teacher_id, full_name
FROM schedule_items
JOIN teachers ON schedule_items.teacher_id = teachers.id
WHERE teacher_id = 4520 and dbeg = '2023-03-06';
но при попытке запуска этого запроса увидим такую ошибку
дело в том, что мы указали в SELECT
первым столбцом id
. А так как мы склеиваем две таблицы и в каждой есть столбец id
,
то запрос не понимает какой id имеется ввиду.
Для решения этой проблемы, мы можем явно указать из какой таблицы взять столбец, вот так:
SELECT schedule_items.id, groups, discipline, ngroup, group_id, teacher_id, full_name
FROM schedule_items
JOIN teachers ON schedule_items.teacher_id = teachers.id
WHERE teacher_id = 4520 and dbeg = '2023-03-06';
и тогда запрос запустится уже без ошибок:
в жизни часто бывает, что надо выводить одинаковые поля из разных таблиц, и писать длинные конструкции вида schedule_items
становится очень неудобно.
Для удобства в sql
можно использовать алисы, чтобы уменьшить длину запроса.
Алиас
– это сокращеное названиеи таблицы, которое мы можем прописать прямо в запросе.
Делается это путем добавления сокращения после названия таблицы в конструкции FROM
либо в JOIN
.
То есть пишем:
и теперь везде где надо обращаться к таблицу schedule_items
можно писать si
. Вот так:
SELECT si.id, groups, discipline, ngroup, group_id, teacher_id, full_name
FROM schedule_items si
JOIN teachers t ON si.teacher_id = t.id
WHERE teacher_id = 4520 and dbeg = '2023-03-06';
если захотим добавить идентификатор препода, то можем вытащить его из таблицы teachers
.
Так как для нее мы указали алиас t
, то достаточно добавить в SELECT
:
SELECT si.id, t.id, groups, discipline, ngroup, group_id, teacher_id, full_name
FROM schedule_items si
JOIN teachers t ON si.teacher_id = t.id
WHERE teacher_id = 4520 and dbeg = '2023-03-06';
Склейка не зависит от фильтров
так как склейка происходит глобально по признаку, то если мы сделаем запрос не фильтруя по преподавателю, у нас все равно все имена успешно подтянутся.
SELECT si.id, groups, discipline, ngroup, group_id, teacher_id, full_name
FROM schedule_items si
JOIN teachers t ON si.teacher_id = t.id
WHERE dbeg = '2023-03-06';
Задание
Напишите два запроса:
- Запрос который выведет расписание вашей подгруппы на день, когда у вас больше всего пар. Как в предыдущем задании, но вместо номера преподавателя выводите ФИО
- Запрос который выведет расписание вашей подгруппы на день, когда у вас больше всего пар. Как в предыдущем задании, но вместо номера аудитории выводите название аудитории