0Pricing
Coding Interview Prep · Урок

LEFT JOIN и сохранение несовпавших строк

Узнайте, что сохраняет LEFT JOIN и как NULL появляются в несовпавших строках.

«LEFT JOIN и сохранение несовпавших строк» — бесплатный урок Coding Interview Prep на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Coding Interview Prep, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Coding Interview Prep содержит 4 уроков всего.

Сценарий собеседования

Интервьюер говорит: «Перечислите всех клиентов и их заказы, включая клиентов, которые никогда ничего не заказывали». INNER JOIN исключает клиентов без заказов, поэтому не выполняет это требование. Здесь нужен LEFT JOIN.

LEFT JOIN сохраняет каждую строку из левой (первой названной) таблицы и присоединяет совпадающие строки из правой таблицы, если они есть. В этом уроке формируется точная мысленная модель, которую ожидают интервьюеры.

Что гарантирует LEFT JOIN

Главное обещание: каждая строка левой таблицы появляется в результате как минимум один раз — с совпадением или без него.

  • Если для строки слева находятся совпадения справа, вы получаете по одной строке результата на каждое совпадение.
  • Если для строки слева нет совпадений, вы всё равно получаете одну строку результата, а все столбцы правой таблицы получают значение NULL.

Именно поэтому интервьюеры называют это внешним соединением: строки, не попавшие в множество совпадений, сохраняются, а не отбрасываются.

Две таблицы

На протяжении всего урока мы используем две простые таблицы. customers содержит всех клиентов, а orders хранит сведения о покупках и ссылается на клиента через customer_id.

Заметьте: у клиента 3 (Кэрол) нет строки в orders. Именно этого клиента без совпадения LEFT JOIN должен сохранить.

-- customers
-- id | name
--  1 | Alice
--  2 | Bob
--  3 | Carol

-- orders
-- id | customer_id | amount
-- 10 |     1       |  50
-- 11 |     1       |  75
-- 12 |     2       |  20

Как написать LEFT JOIN

Синтаксис похож на синтаксис внутреннего соединения: вместо INNER используется LEFT (слово OUTER необязательно: LEFT JOIN и LEFT OUTER JOIN полностью идентичны).

Таблица, записанная перед ключевым словом, является сохраняемой левой стороной. Порядок важен: customers LEFT JOIN orders сохраняет всех клиентов, а не все заказы.

SELECT c.name, o.amount
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.id;

Чтение результата

Вот результат выполнения этого запроса. Для Алисы найдено два совпадения, поэтому она появляется дважды. Для Боба найдено одно совпадение. Для Кэрол совпадений нет, поэтому она всё равно появляется со значением NULL в столбце amount.

Единственная строка Кэрол со значением NULL — характерный признак LEFT JOIN. Интервьюер, наблюдающий за вашими рассуждениями, хочет услышать: «Несовпавшие строки слева сохраняются, а справа получают значения NULL».

-- name  | amount
-- Alice |  50
-- Alice |  75
-- Bob   |  20
-- Carol | NULL   <-- preserved, no match

Откуда берутся значения NULL

Значение NULL нигде не хранится. База данных создаёт его, поскольку нет строки правой таблицы, которая могла бы предоставить значение amount.

Каждый столбец, выбранный из правой таблицы, становится NULL для строки слева без совпадения: o.id, o.customer_id и o.amount в строке Кэрол имеют значение NULL. Это важно: значение o.customer_id, равное NULL, не означает, что у клиента нет идентификатора; это означает, что подходящего заказа вообще не было.

Подсчёт заказов для каждого клиента

Частый дополнительный вопрос: «Сколько заказов есть у каждого клиента, включая клиентов с нулём заказов?» LEFT JOIN вместе с COUNT отлично подходит, но считать нужно столбец правой таблицы, а не *.

COUNT(o.id) игнорирует значения NULL, поэтому для Кэрол получится 0. COUNT(*) ошибочно вернёт для Кэрол 1, поскольку созданная системой строка со значениями NULL всё равно считается строкой.

SELECT c.name, COUNT(o.id) AS order_count
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name;
-- Alice | 2
-- Bob   | 1
-- Carol | 0

Ловушка при сравнении COUNT(*) и COUNT по столбцу

Это классическая ловушка на собеседовании. После LEFT JOIN строка левой таблицы без совпадения физически присутствует в результате, а столбцы правой таблицы содержат значения NULL.

  • COUNT(*) считает эту строку и возвращает 1 для клиента без заказов.
  • COUNT(o.id) пропускает значение NULL и правильно возвращает 0.

Если нужны настоящие нули, всегда считайте столбец, который принимает значение NULL при отсутствии совпадения.

-- WRONG: Carol shows 1
SELECT c.name, COUNT(*) AS n
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name;

Суммирование с LEFT JOIN

Другие агрегатные функции, кроме COUNT, также корректно работают с созданными системой значениями NULL. SUM игнорирует значения NULL, поэтому для клиента без совпадений получится NULL, а не ошибка.

Интервьюеры часто хотят видеть в отчёте ноль вместо NULL. Оберните агрегат в COALESCE, чтобы подставить значение по умолчанию.

SELECT c.name,
       COALESCE(SUM(o.amount), 0) AS total_spent
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name;
-- Alice | 125
-- Bob   |  20
-- Carol |   0

Левая и правая таблица: точная формулировка

Если интервьюер спрашивает: «Какая таблица сохраняется?», уверенно отвечайте: таблица слева от ключевого слова JOIN. Читайте запрос слева направо.

A LEFT JOIN B означает: сохранить все строки A. Чтобы вместо этого сохранить все строки B, переставьте таблицы и напишите B LEFT JOIN A либо используйте RIGHT JOIN. Большинство команд предпочитает использовать только LEFT JOIN для удобства чтения, просто меняя порядок таблиц.

Мысленный контрольный список

Увидев LEFT JOIN на собеседовании, вслух пройдите следующий список:

  • Какая сторона сохраняется? Левая таблица, сохраняются все её строки.
  • Что происходит с несовпавшими строками? Они появляются один раз, а справа получают значения NULL.
  • Нужно посчитать? Используйте COUNT(right_col), чтобы получить настоящие нули.
  • Нужно просуммировать? Оберните результат в COALESCE, если нужен 0, а не NULL.

Проговаривание этого списка демонстрирует строгость мышления на уровне опытного разработчика.

Быстрая проверка

Проверьте понимание LEFT JOIN на примере подсчёта.

Повторение

LEFT JOIN сохраняет каждую строку левой таблицы. Совпавшие строки слева объединяются с соответствующими строками справа, а несовпавшие строки слева сохраняются один раз, при этом все столбцы правой таблицы получают значение NULL.

  • Левая таблица — это таблица перед ключевым словом JOIN.
  • Созданные системой значения NULL указывают на строки без совпадений.
  • COUNT(right_col) даёт настоящие нули, а COUNT(*) — нет.
  • COALESCE(SUM(...), 0) превращает итоговое значение NULL в ноль.

Это основа для поиска отсутствующих данных и антисоединений в следующих уроках.

Часто задаваемые вопросы

Урок «LEFT JOIN и сохранение несовпавших строк» бесплатный?

Да — полный текст урока «LEFT JOIN и сохранение несовпавших строк» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Coding Interview Prep, подпишись на CoddyKit PRO. Курс Coding Interview Prep содержит 4 уроков всего.

Чему я научусь в уроке «LEFT JOIN и сохранение несовпавших строк»?

Узнайте, что сохраняет LEFT JOIN и как NULL появляются в несовпавших строках. Ты практикуешь Coding Interview Prep с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Coding Interview Prep?

Предыдущий опыт не требуется. Coding Interview Prep на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «LEFT JOIN и сохранение несовпавших строк»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Coding Interview Prep?

Да. Каждый урок Coding Interview Prep включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. LEFT JOIN и сохранение несовпавших строк
  2. Смысл RIGHT и FULL OUTER JOIN
  3. Поиск строк без совпадений (антиобъединение)
  4. Ловушка WHERE при внешнем объединении
← Назад к Coding Interview Prep