JOIN: INNER, LEFT и RIGHT
Соединяем таблицы по ключу и разбираемся, чем INNER отличается от LEFT и RIGHT JOIN.
JOIN объединяет строки из двух таблиц по условию связи (обычно по совпадению ключей) в один результат.
Подготовим данные
Возьмём пользователей и их заказы. Учтём, что у одного пользователя заказов нет — на нём и увидим разницу между видами JOIN.
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER,
amount INTEGER
);
INSERT INTO users (name) VALUES ('Анна'), ('Борис'), ('Вера');
INSERT INTO orders (user_id, amount) VALUES (1, 500), (1, 300), (2, 700);
SELECT u.name, o.amount
FROM users u
INNER JOIN orders o ON o.user_id = u.id;
Вывод:
name amount Анна 500 Анна 300 Борис 700
INNER JOIN вернул только тех, у кого есть заказы. Вера не попала — у неё заказов нет.
LEFT JOIN — сохранить все левые строки
LEFT JOIN берёт все строки левой таблицы, а если справа совпадения нет — подставляет NULL. Так мы увидим и пользователей без заказов.
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER,
amount INTEGER
);
INSERT INTO users (name) VALUES ('Анна'), ('Борис'), ('Вера');
INSERT INTO orders (user_id, amount) VALUES (1, 500), (2, 700);
SELECT u.name, o.amount
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
ORDER BY u.name;
Вывод:
name amount Анна 500 Борис 700 Вера
У Веры в amount — пусто (NULL): заказа нет, но сама строка осталась. Это типичный способ найти «сирот»: WHERE o.id IS NULL покажет тех, у кого нет связанных записей.
RIGHT JOIN
RIGHT JOIN — зеркало LEFT JOIN: сохраняет все строки правой таблицы. На практике его используют редко: обычно проще поменять таблицы местами и написать LEFT JOIN. Запомните соответствие: A RIGHT JOIN B ≡ B LEFT JOIN A.
Памятка по JOIN
| JOIN | Что возвращает |
INNER JOIN | только совпавшие пары из обеих таблиц |
LEFT JOIN | все строки левой + совпавшие правой (иначе NULL) |
RIGHT JOIN | все строки правой + совпавшие левой (иначе NULL) |
Замечание: в MySQL нет FULL OUTER JOIN (в отличие от некоторых других СУБД) — его эмулируют объединением LEFT и RIGHT через UNION.
Итог
INNER JOIN— пересечение: только строки, у которых есть пара.LEFT JOIN— все левые строки; для непарных правые поля = NULL.RIGHT JOIN— зеркало LEFT; на практике почти всегда заменяется на LEFT.LEFT JOIN ... WHERE правый.id IS NULLнаходит строки без связанных записей.