Зависимая таблица

Теперь немного усложним наши запросы. Добавим в нашу базу данных новую таблицу 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.