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 BB 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 находит строки без связанных записей.
Проверьте себя
1. Что вернёт INNER JOIN для пользователя, у которого нет заказов?
Aстроку с NULL вместо заказа
Bничего — такой пользователь не попадёт в результат
Cошибку
Dвсе его данные дважды
2. Чем LEFT JOIN отличается от INNER JOIN?
ALEFT JOIN работает быстрее
BLEFT JOIN сохраняет все строки левой таблицы, подставляя NULL при отсутствии пары
CLEFT JOIN меняет таблицы местами
Dразницы нет
3. Как найти пользователей без единого заказа?
AINNER JOIN orders
BLEFT JOIN orders ... WHERE orders.id IS NULL
Cпросто SELECT из users
DRIGHT JOIN users
Поддержать проект