Зависимая таблица
Теперь немного усложним наши запросы. Добавим в нашу базу данных новую таблицу task с задачами для наших сотрудников. И посмотрим, какие в ней есть записи:
SELECT * FROM task
Результат такого запроса:
id | emploee_id | name | deadline |
---|---|---|---|
1 | 1 | Исправить багу на фронтенде | 2022-06-01 |
2 | 2 | Исправить багу на бэкенде | 2022-06-15 |
3 | 5 | Купить кофе | 2022-07-01 |
4 | 5 | Купить кофе | 2022-08-01 |
5 | 5 | Купит кофе | 2022-09-01 |
6 | (NULL) | Убрать офис | (NULL) |
7 | 4 | Наслаждаться жизнью | (NULL) |
8 | 6 | Наслаждаться жизнью | (NULL) |
В этой таблице есть всего 4 колонки:
- id — уникальный номер задания (и строки в таблице);
- employee_id — ID сотрудника из таблицы employee, на которого назначена задача;
- name — название и описание задачи;
- deadline — время до которого нужно выполнить задачу.
Обрати внимание на несколько нюансов. Задача N6 не имеет employee_id, у нас нет уборщицы. Задача есть, а исполнителя нет. Такое бывает.
Также у задач 6-9 нет установленного дедлайна. Такое бывает, когда задача должна делаться регулярно и беспрерывно. Например, офис нужно убирать каждый день, ну и наслаждаться жизнью тоже нужно каждый день :)
Если в одной таблице используются ID из другой таблицы, то такая таблица называется зависимой.
Запрос к нескольким таблицам
Вот мы видим в таблице task, что есть два задания “Наслаждается жизнью”. Как нам узнать, кто именно эти счастливчики?
Для этого в SQL можно выполнить запрос сразу к двум таблицам. Вообще в SQL можно выполнять запрос к любому количеству таблиц одновременно. Общий формат такого запроса:
SELECT колонки
FROM таблица1, таблица2, таблицаN
Важно! Если ты напишешь запрос к нескольким таблицам одновременно, то в результате получишь так называемое декартово произведение строк таблиц. К каждой строке из первой таблицы будет приклеена каждая строка из второй таблицы и так далее.
То есть если в первой таблице у вас 5 строк, а во второй 10, то всего у вас будет 50 строк. На языке Java этот запрос выглядел бы примерно так:
for (String row1 : table1)
{
for (String row2 : table2)
{
System.out.println(row1 + row2);
}
}
Давай напишем наш запрос сразу к двум таблицам и поострим, что получится:
SELECT * FROM employee, task
И результат такого запроса:
id | name | occupation | salary | age | id | emploee | _id | name | deadline |
---|---|---|---|---|---|---|---|---|---|
1 | Иванов Иван | Программист | 100000 | 25 | 1 | 1 | Исправить багу на фронтенде | 2022-06-01 | |
2 | Петров Петр | Программист | 80000 | 23 | 1 | 1 | Исправить багу на фронтенде | 2022-06-01 | |
3 | Иванов Сергей | Тестировщик | 40000 | 30 | 1 | 1 | Исправить багу на фронтенде | 2022-06-01 | |
4 | Рабинович Мойша | Директор | 200000 | 35 | 1 | 1 | Исправить багу на фронтенде | 2022-06-01 | |
5 | Кириенко Анастасия | Офис-менеджер | 40000 | 25 | 1 | 1 | Исправить багу на фронтенде | 2022-06-01 | |
6 | Васька | кот | 1000 | 3 | 1 | 1 | Исправить багу на фронтенде | 2022-06-01 | |
1 | Иванов Иван | Программист | 100000 | 25 | 2 | 2 | Исправить багу на бэкенде | 2022-06-15 | |
2 | Петров Петр | Программист | 80000 | 23 | 2 | 2 | Исправить багу на бэкенде | 2022-06-15 | |
3 | Иванов Сергей | Тестировщик | 40000 | 30 | 2 | 2 | Исправить багу на бэкенде | 2022-06-15 | |
4 | Рабинович Мойша | Директор | 200000 | 35 | 2 | 2 | Исправить багу на бэкенде | 2022-06-15 | |
5 | Кириенко Анастасия | Офис-менеджер | 40000 | 25 | 2 | 2 | Исправить багу на бэкенде | 2022-06-15 |
Всего строк результата у нас 48, но тут я привел всего 11. Иначе просто места не хватит.
Обрати внимание на три вещи:
- Колонки с одинаковыми именами: id. Это id из таблицы employee и id из таблицы task.
- Строки каждой таблицы повторяются. В левой колонке после ID 6 снова идет ID = 1.
- У нас есть бессмысленные строки, когда, например id (из таблицы employee) равно 6 и в той же строке employee_id равно 1.
Убираем бессмысленные строки
В нашей результирующей таблице, которая является декартовым произведением всех строк двух таблиц employee и task слишком много строк.
Логично, что если в строке employee_id равно 3, то она должна приклеиваться только к строке из таблицы employee, где id равно 3. Давай попробуем исправить это недоразумение с помощью WHERE.
Напишем такой запрос:
SELECT * FROM employee, task
WHERE emploee.id = task.emploee_id
И результат такого запроса:
id | name | occupation | salary | age | id | emploee_id | name | deadline |
---|---|---|---|---|---|---|---|---|
1 | Иванов Иван | Программист | 100000 | 25 | 1 | 1 | Исправить багу на фронтенде | 2022-06-01 |
2 | Петров Петр | Программист | 80000 | 23 | 2 | 2 | Исправить багу на бэкенде | 2022-06-15 |
4 | Рабинович Мойша | Директор | 200000 | 35 | 7 | 4 | Наслаждаться жизнью | (NULL) |
5 | Кириенко Анастасия | Офис-менеджер | 40000 | 25 | 3 | 5 | Купить кофе | 2022-07-01 |
5 | Кириенко Анастасия | Офис-менеджер | 40000 | 25 | 4 | 5 | Купить кофе | 2022-08-01 |
5 | Кириенко Анастасия | Офис-менеджер | 40000 | 25 | 5 | 5 | Купит кофе | 2022-09-01 |
6 | Васька | кот | 1000 | 3 | 8 | 6 | Наслаждаться жизнью | (NULL) |
Хорошая новость — у нас исчезли бессмысленные строки: id из первой колонки всегда равно employee_id.
Плохая новость — исчезли задачи, которые ни на кого не назначены, такие как уборка офиса. Их employee_id был равен NULL, поэтому они были отброшены после выполнения WHERE.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ