Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. INNER JOIN
inner_join

INNER JOIN

Внутреннее соединение таблиц: экви- и неэкви-условия, множественные условия

INNER JOIN

INNER JOIN — это самый распространённый тип соединения, который возвращает только те строки, для которых есть совпадение в обеих таблицах.

#Синтаксис INNER JOIN

SELECT <колонки> FROM таблица1 INNER JOIN таблица2 ON таблица1.колонка = таблица2.колонка;

Ключевое слово INNER можно опустить — JOIN по умолчанию означает INNER JOIN:

SELECT <колонки> FROM таблица1 JOIN таблица2 ON таблица1.колонка = таблица2.колонка;

#Пример данных

Используем те же таблицы, что и в предыдущей теме:

CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(100) UNIQUE ); CREATE TABLE orders ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id), product VARCHAR(100), amount DECIMAL(10, 2) ); INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com'), ('Bob', 'bob@example.com'), ('Charlie', 'charlie@example.com'), ('Diana', 'diana@example.com'); INSERT INTO orders (user_id, product, amount) VALUES (1, 'Laptop', 1200.00), (1, 'Mouse', 50.00), (2, 'Keyboard', 150.00), (5, 'Monitor', 300.00); -- заказ для несуществующего пользователя!

Данные:

users:                          orders:
+----+---------+----------------+----+---------+----------+--------+
| id | name    | email          | id | user_id | product  | amount |
+----+---------+----------------+----+---------+----------+--------+
| 1  | Alice   | alice@...      | 1  | 1       | Laptop   | 1200.00|
| 2  | Bob     | bob@...        | 2  | 1       | Mouse    | 50.00  |
| 3  | Charlie | charlie@...    | 3  | 2       | Keyboard | 150.00 |
| 4  | Diana   | diana@...      | 4  | 5       | Monitor  | 300.00 |
+----+---------+----------------+----+---------+----------+--------+

#Базовый пример INNER JOIN

SELECT u.name, o.product, o.amount FROM users u JOIN orders o ON u.id = o.user_id;

Результат:

+-------+----------+--------+
| name  | product  | amount |
+-------+----------+--------+
| Alice | Laptop   | 1200.00|
| Alice | Mouse    | 50.00  |
| Bob   | Keyboard | 150.00 |
+-------+----------+--------+

Что произошло:

  • Charlie и Diana отсутствуют — у них нет заказов
  • Заказ с user_id = 5 не попал — пользователя с id = 5 не существует
  • Alice aparece дважды — связь один-ко-многим

#Эквисоединение (Equijoin)

Наиболее распространённая форма INNER JOIN — эквисоединение, где условие использует оператор равенства (=):

-- Эквисоединение по первичному и внешнему ключу FROM users JOIN orders ON users.id = orders.user_id

Это наиболее эффективный тип соединения, особенно если обе колонки проиндексированы.

#Неэксисоединение (Nonequijoin)

INNER JOIN может использовать любые операторы сравнения, не только =:

-- Диапазонное соединение SELECT e.name, s.grade, s.min_salary, s.max_salary FROM employees e JOIN salary_grades s ON e.salary BETWEEN s.min_salary AND s.max_salary;
-- Соединение по неравенству SELECT a.id, b.id FROM table_a a JOIN table_b b ON a.value > b.value;

#Множественные условия в ON

Можно указывать несколько условий в ON, соединяя их через AND:

-- Соединение по составному ключу SELECT * FROM order_items oi JOIN products p ON oi.product_id = p.id AND oi.warehouse_id = p.warehouse_id;
-- Дополнительные условия фильтрации в ON SELECT u.name, o.product FROM users u JOIN orders o ON u.id = o.user_id AND o.amount > 100;

Важно: Условия в ON применяются до соединения таблиц. Условия в WHERE — после. Для INNER JOIN разница не критична, но для OUTER JOIN это существенно.

#Соединение нескольких таблиц

INNER JOIN позволяет соединять множество таблиц:

SELECT u.name AS user_name, o.id AS order_id, p.name AS product_name, c.name AS category_name FROM users u JOIN orders o ON u.id = o.user_id JOIN products p ON o.product_id = p.id JOIN categories c ON p.category_id = c.id;

Порядок таблиц в INNER JOIN не важен — оптимизатор PostgreSQL сам выберет оптимальный план.

#Агрегация с INNER JOIN

INNER JOIN часто используется с агрегатными функциями:

-- Количество заказов и общая сумма по каждому пользователю SELECT u.name, COUNT(o.id) AS order_count, SUM(o.amount) AS total_amount FROM users u JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.name;

Результат:

+-------+-------------+--------------+
| name  | order_count | total_amount |
+-------+-------------+--------------+
| Alice | 2           | 1250.00      |
| Bob   | 1           | 150.00       |
+-------+-------------+--------------+

#INNER JOIN с фильтрацией

Часто комбинируют JOIN с WHERE для дополнительной фильтрации:

-- Только заказы дороже $100 SELECT u.name, o.product, o.amount FROM users u JOIN orders o ON u.id = o.user_id WHERE o.amount > 100;
-- Только пользователи с именем на 'A' SELECT u.name, o.product FROM users u JOIN orders o ON u.id = o.user_id WHERE u.name LIKE 'A%';

#Производительность INNER JOIN

Для эффективной работы INNER JOIN важно:

  1. Индексы на колонках соединения:

    CREATE INDEX idx_orders_user_id ON orders(user_id);
  2. Статистика актуальна:

    ANALYZE users; ANALYZE orders;
  3. Используйте EXPLAIN для анализа плана:

    EXPLAIN ANALYZE SELECT * FROM users u JOIN orders o ON u.id = o.user_id;

#Распространённые ошибки

#1. Забытое условие ON

-- ОШИБКА: декартово произведение! SELECT * FROM users, orders; -- Правильно: SELECT * FROM users JOIN orders ON users.id = orders.user_id;

#2. Неправильный тип данных в условии

-- Плохо: неявное приведение типов SELECT * FROM users u JOIN orders o ON u.id = o.user_id::TEXT; -- Хорошо: типы совпадают SELECT * FROM users u JOIN orders o ON u.id = o.user_id;

#3. Соединение по неиндексированным колонкам

-- Медленно: нет индекса на email SELECT * FROM users u JOIN orders o ON u.email = o.customer_email; -- Быстро: индекс на foreign key SELECT * FROM users u JOIN orders o ON u.id = o.user_id;

#Когда использовать INNER JOIN

СценарийПодходит
Нужны только строки с совпадениями в обеих таблицах✅ Да
Нужно найти пользователей без заказов❌ Нет (используйте LEFT JOIN + WHERE NULL)
Нужно показать всех пользователей с их заказами❌ Нет (используйте LEFT JOIN)
Агрегация только по имеющимся данным✅ Да

Далее: Внешние соединения: LEFT, RIGHT, FULL