Соединение таблиц: INNER JOIN
Собираем строки из двух (или трёх) таблиц в один результат
- объяснить, почему данные хранятся в нескольких таблицах,
- написать
INNER JOINс условиемON, - использовать короткие псевдонимы таблиц, чтобы запросы были аккуратными,
- соединить три таблицы в цепочку,
- предсказать, какие строки INNER JOIN оставит, а какие отбросит.
1. Почему данные лежат во многих таблицах
Представьте, что школа хранит всё в одной огромной таблице: в каждой строке ученика ещё раз повторяется полное название класса и имя учителя. Если Математику ведёт Mr. Adams, вам придётся писать "Math" и "Mr. Adams" для каждого ученика этого класса. Это тратит место и, что хуже, ведёт к ошибкам: исправите имя учителя в одной строке и забудете в остальных — и данные начнут противоречить сами себе.
Аккуратное решение — хранить каждый вид сущности в своей таблице и связывать их ключами (первичные и внешние ключи вы встречали в прошлой теме):
- таблица
students(по одной строке на ученика), - таблица
classes(по одной строке на класс), - таблица
teachers(по одной строке на учителя).
Каждая строка ученика хранит маленький class_id вместо полного названия класса. Название написано один раз в classes. Чтобы увидеть название класса рядом с учеником, мы просим базу данных соединить две таблицы обратно.
2. Наша учебная база данных школы
Эту крошечную базу мы будем использовать весь урок. Создайте её один раз, а затем выполняйте запросы ниже.
CREATE TABLE teachers (
teacher_id INT PRIMARY KEY,
teacher_name VARCHAR(50)
);
INSERT INTO teachers VALUES
(1, 'Mr. Adams'),
(2, 'Ms. Baker'),
(3, 'Mr. Carter');
CREATE TABLE classes (
class_id INT PRIMARY KEY,
class_name VARCHAR(50),
teacher_id INT
);
INSERT INTO classes VALUES
(101, 'Math', 1),
(102, 'Science', 2),
(103, 'Art', 3);
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(50),
class_id INT
);
INSERT INTO students VALUES
(1, 'Alice', 101),
(2, 'Ben', 101),
(3, 'Carla', 102),
(4, 'Dan', 103),
(5, 'Eve', NULL);
Итак, три таблицы содержат:
teachers
| teacher_id | teacher_name |
|---|---|
| 1 | Mr. Adams |
| 2 | Ms. Baker |
| 3 | Mr. Carter |
classes
| class_id | class_name | teacher_id |
|---|---|---|
| 101 | Math | 1 |
| 102 | Science | 2 |
| 103 | Art | 3 |
students
| student_id | name | class_id |
|---|---|---|
| 1 | Alice | 101 |
| 2 | Ben | 101 |
| 3 | Carla | 102 |
| 4 | Dan | 103 |
| 5 | Eve | NULL |
Обратите внимание: у Eve значение class_id = NULL — она ещё не записана в класс. Запомните её; она поможет понять, что INNER JOIN отбрасывает.