Перейти к содержанию

JOIN и связи

SQL JOIN: как соединять таблицы

JOIN нужен, когда данные разложены по разным таблицам и их надо собрать в одну выборку.

Зачем вообще JOIN

В нормальной базе данные разделены:

  • пользователи — отдельно,
  • заказы — отдельно,
  • товары — отдельно,
  • позиции заказа — отдельно.

Чтобы получить, например, «заказы + имя пользователя», мы делаем JOIN.


INNER JOIN: только совпавшие строки

SQL
SELECT
  o.id        AS order_id,
  u.name      AS user_name,
  o.status,
  o.created_at
FROM orders o
JOIN users u ON u.id = o.user_id
ORDER BY o.created_at DESC;

Как читать: «Возьми orders, соедини с users по условию users.id = orders.user_id».


LEFT JOIN: все слева, даже если справа ничего нет

Это важно, когда справа может не быть пары.

Пример: показать всех пользователей и количество заказов у каждого.

SQL
SELECT
  u.id,
  u.name,
  COUNT(o.id) AS orders_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.name
ORDER BY orders_count DESC;

LEFT JOIN гарантирует, что пользователи без заказов тоже попадут в результат (у них orders_count = 0).


Виды JOIN

sql-03-joins.svg INNER, LEFT, RIGHT и FULL JOIN — базовые типы соединений.

FULL JOIN есть не во всех СУБД (в MySQL исторически нет напрямую), но концепцию понимать полезно.


Реальный JOIN по 3–4 таблицам: заказ и его состав

Посчитаем позиции заказа: товар, количество, стоимость строки.

SQL
SELECT
  o.id   AS order_id,
  u.name AS user_name,
  p.name AS product_name,
  oi.qty,
  oi.price,
  (oi.qty * oi.price) AS line_total
FROM orders o
JOIN users u       ON u.id = o.user_id
JOIN order_items oi ON oi.order_id = o.id
JOIN products p    ON p.id = oi.product_id
ORDER BY o.id, p.name;

Почему строк становится больше? Если связь «один-ко-многим», JOIN «размножает» строки — это нормально. Важно лишь соединять по правильным ключам.