SQL INNER JOIN: объединение строк из двух таблиц

В SQL при использовании INNER JOIN вы получаете только те строки, где условие соединения совпадает в обеих таблицах. Используйте его, чтобы объединять связанные данные — например, связывать записи со значениями из справочников — когда строки без совпадения нужно исключить из результата. Поскольку предикат соединения должен выполняться с обеих сторон, любая строка с NULL в ключе соединения или без соответствующей пары автоматически отфильтровывается.

Пример SQL INNER JOIN Для Объединения Связанных Таблиц

Вывод:

Результат появится здесь...

Вывод:

+----------+-------------+
| employee | department  |
+----------+-------------+
| Alma     | Разработка  |
| Ben      | Разработка  |
| Cara     | Продажи     |
+----------+-------------+
3 row(s)

Как Работает Этот Пример

  1. departments хранит три отдела; employees хранит четырех сотрудников, у каждого есть внешний ключ dept_id. У Dan значение dept_id равно NULL.
  2. INNER JOIN departments d ON d.id = e.dept_id сопоставляет каждую строку сотрудника со строкой отдела, где id отдела равен dept_id сотрудника. Сохраняются только пары, где совпадение есть с обеих сторон.
  3. У Dan dept_id = NULL. Оператор = возвращает unknown, если один из операндов равен NULL, поэтому Dan не совпадает ни с одним отделом и исключается.
  4. В отделе HR (id 3) нет сотрудников, которые на него ссылаются, поэтому он тоже не появляется: INNER JOIN отбрасывает несовпавшие строки с обеих сторон.

Что Такое SQL INNER JOIN?

INNER JOIN возвращает пересечение двух таблиц по предикату соединения. Логически он сохраняет только те пары строк, где условие ON вычисляется в true. Физическое выполнение зависит от движка и формы данных (nested loops, hash join, merge join), но результирующий набор всегда содержит только совпавшие строки.

INNER JOIN vs LEFT JOIN

INNER JOINLEFT JOIN
Возвращает только совпавшие строки из обеих таблицВозвращает все строки из левой таблицы и подставляет NULL там, где совпадения нет
Несовпавшие строки молча отбрасываютсяНесовпавшие строки слева сохраняются, а правые столбцы заполняются NULL
Используется, когда отсутствие совпадения означает некорректные данныеИспользуется, когда нужно видеть все записи левой стороны независимо от совпадений

Правило: выбирайте INNER JOIN, когда каждая строка результата должна содержать корректные данные из обеих таблиц. Переключайтесь на LEFT JOIN, когда нужно сохранять строки даже без совпадения справа.

Частые Ошибки С SQL INNER JOIN

Отсутствующий или всегда истинный предикат соединения

Пропуск ON (или условие, которое всегда истинно) создает декартово произведение: каждый сотрудник соединяется с каждым отделом.

-- Неправильно: декартово произведение (12 строк из 4 × 3)
SELECT * FROM employees, departments;

-- Правильно: явный предикат соединения
SELECT * FROM employees e
INNER JOIN departments d ON d.id = e.dept_id;

Неуникальные ключи соединения вызывают мультипликацию строк

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

INNER JOIN vs EXISTS

Используйте INNER JOIN, когда в выводе нужны столбцы из обеих таблиц. Используйте EXISTS, когда нужно только отфильтровать строки по факту наличия связанной строки. EXISTS также предотвращает мультипликацию строк, если подзапрос может вернуть несколько совпадений, а планировщик запроса часто может остановиться после первого совпадения.

-- EXISTS: одна строка на сотрудника, у которого есть подходящий отдел
SELECT e.name FROM employees e
WHERE EXISTS (SELECT 1 FROM departments d WHERE d.id = e.dept_id);

Заметки О Производительности

Индексируйте столбцы, которые участвуют в предикате соединения (dept_id и departments.id в этом примере). Без индекса движок может многократно сканировать внутреннюю таблицу. Для больших таблиц проверяйте план через EXPLAIN QUERY PLAN: вместо SCAN лучше видеть USING INDEX или SEARCH.