← Назад к вопросам

Для чего нужен INNER JOIN?

1.0 Junior🔥 241 комментариев
#Базы данных (SQL)

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# INNER JOIN: назначение и примеры

Определение

INNER JOIN - это операция в SQL, которая объединяет две таблицы по совпадающим значениям определенного столбца, возвращая только те строки, которые имеют соответствия в обеих таблицах.

Таблица A    INNER JOIN    Таблица B
┌────────────────────────────────┐
│  Строки, где ID совпадают     │
└────────────────────────────────┘

Базовый синтаксис

SELECT 
  a.id,
  a.name,
  b.email
FROM users AS a
INNER JOIN orders AS b ON a.id = b.user_id;

Практический пример с данными

Исходные таблицы

Таблица users:

id | name   | city
---|--------|--------
1  | Alice  | NYC
2  | Bob    | LA
3  | Carol  | Chicago
4  | David  | NYC

Таблица orders:

id | user_id | amount
---|---------|--------
1  | 1       | 100
2  | 2       | 200
3  | 1       | 150
5  | 5       | 300  (user_id 5 не существует в users)

INNER JOIN запрос

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

Результат

id | name  | order_id | amount
---|-------|----------|--------
1  | Alice | 1        | 100
2  | Bob   | 2        | 200
1  | Alice | 3        | 150

Заметь: user_id 5 исключена, потому что нет соответствующей строки в users.

Для чего нужен INNER JOIN

1. Получение связанных данных из двух таблиц

-- Получить все заказы с информацией о клиенте
SELECT 
  u.name as customer_name,
  o.id as order_id,
  o.amount,
  o.created_at
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

2. Фильтрация по условиям в обеих таблицах

-- Получить заказы клиентов из NYC, которые больше 150
SELECT 
  u.name,
  o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE u.city = 'NYC' AND o.amount > 150;

3. Объединение данных с условием соответствия

-- Получить список сотрудников и их офисы
SELECT 
  e.name as employee,
  d.name as department,
  d.location
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;

4. Исключение неполных данных

-- Получить только пользователей, которые сделали заказы
-- (исключаются пользователи без заказов)
SELECT DISTINCT
  u.id,
  u.name,
  u.email
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

INNER JOIN vs другие JOINы

LEFT JOIN

SELECT 
  u.name,
  o.id as order_id
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

Результат (включает все из users, даже без заказов):

name  | order_id
------|----------
Alice | 1
Alice | 3
Bob   | 2
Carol | NULL    <- Carol без заказов
David | NULL    <- David без заказов

INNER JOIN (то же самое, но без Carol и David)

SELECT 
  u.name,
  o.id as order_id
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

Результат:

name  | order_id
------|----------
Alice | 1
Alice | 3
Bob   | 2

Примеры с Python и SQLAlchemy

Пример 1: Simple INNER JOIN

from sqlalchemy import create_engine, select
from sqlalchemy.orm import Session

# SQLAlchemy models
class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True)
    name = Column(String)

class Order(Base):
    __tablename__ = "orders"
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey("users.id"))
    amount = Column(Float)

# INNER JOIN с SQLAlchemy
query = select(User.name, Order.id, Order.amount).join(Order)
result = session.execute(query).fetchall()

# Результат:
# [('Alice', 1, 100.0), ('Bob', 2, 200.0), ('Alice', 3, 150.0)]

Пример 2: INNER JOIN с условием

query = select(User.name, Order.amount).join(Order).where(Order.amount > 150)
result = session.execute(query).fetchall()

# Результат:
# [('Bob', 200.0), ('Alice', 150.0)]

Пример 3: Multiple JOINs

# Таблицы: users -> orders -> products
class Product(Base):
    __tablename__ = "products"
    id = Column(Integer, primary_key=True)
    order_id = Column(Integer, ForeignKey("orders.id"))
    name = Column(String)
    price = Column(Float)

# Получить все продукты в заказах пользователя Alice
query = (
    select(User.name, Product.name, Product.price)
    .join(Order)
    .join(Product)
    .where(User.name == "Alice")
)
result = session.execute(query).fetchall()

Пример реального сценария: E-commerce

-- Получить отчет о продажах: клиент, товар, количество, сумма
SELECT 
  u.name as customer,
  p.name as product,
  oi.quantity,
  oi.price,
  (oi.quantity * oi.price) as total
FROM users u
INNER JOIN orders o ON u.id = o.user_id
INNER JOIN order_items oi ON o.id = oi.order_id
INNER JOIN products p ON oi.product_id = p.id
WHERE o.status = 'completed';

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

✅ Используй INNER JOIN когда:

  1. Нужны только совпадающие записи

    • Зарплата сотрудников с отделами (каждый сотрудник в отделе)
  2. Нужно исключить неполные данные

    • Только пользователей с заказами
    • Только сотрудников с проектами
  3. Связь один-к-одному или один-ко-многим

    • Пользователи и их профили
    • Клиенты и их заказы

❌ Избегай INNER JOIN когда:

  1. Нужны все строки из одной таблицы

    • Все пользователи, даже без заказов → LEFT JOIN
  2. Нужны все строки из обеих таблиц

    • Все заказы и все товары → FULL OUTER JOIN
  3. Нужны непарные записи

    • Товары, которые никто не покупал → LEFT JOIN с условием IS NULL

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

-- ❌ Плохо: SELECT * без индексов
SELECT * 
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

-- ✅ Хорошо: SELECT нужные столбцы с индексами
SELECT u.id, u.name, o.id, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

-- Убедись, что есть индексы:
CREATE INDEX idx_orders_user_id ON orders(user_id);

Общая таблица типов JOIN-ов

JOINОписаниеИспользуется для
INNER JOINТолько совпадающиеСвязанные данные
LEFT JOINВсе из левой таблицыВсе, даже без пары
RIGHT JOINВсе из правой таблицыОбратный LEFT
FULL OUTERВсе из обеих таблицВсе записи
CROSS JOINДекартово произведениеВсе комбинации

Вывод

INNER JOIN - это основная операция для объединения таблиц. Используй его когда нужны только совпадающие строки из обеих таблиц. Это самый часто используемый JOIN в реальных приложениях, особенно для получения связанных данных из нормализованной БД. Помни: INNER JOIN исключает строки без соответствий, поэтому проверяй, что это именно то, что нужно.