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

Какие знаешь типы соединения таблиц SQL?

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

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

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

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

Типы соединения таблиц (JOIN) в SQL

Основной синтаксис

SELECT columns
FROM table1
JOIN table2 ON table1.id = table2.table1_id;

1. INNER JOIN (внутреннее соединение)

Что возвращает: только совпадающие строки из обеих таблиц

Синтаксис:

SELECT q.title, a.text, u.name
FROM Question q
INNER JOIN Answer a ON q.id = a.question_id
INNER JOIN User u ON a.user_id = u.id;

Диаграмма:

Question       Answer
┌────┐         ┌────┐
│ Q1 │    ──→  │ A1 │  (совпадение)
│ Q2 │    ──→  │ A2 │  (совпадение)
│ Q3 │    X    │    │  (Q3 без ответов - не будет в результате)
└────┘         └────┘

Результат: Q1-A1, Q2-A2 (только пересечение)

Визуально (диаграмма Венна):

    table1    table2
      ┌────────────┐
      │   MATCH    │
      │ (INNER)    │
      └────────────┘

Пример результата:

title                  | text              | name
───────────────────────┼──────────────────┼───────
System Design          | Use load balancer | John
Database Optimization  | Index your data   | Jane

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

  • Нужны данные ТОЛЬКО если есть соответствие
  • Самый частый JOIN
  • Забыть что-то - нечего, всё есть

2. LEFT JOIN (левое внешнее соединение)

Что возвращает: ВСЕ строки из левой таблицы + совпадающие из правой (NULL если нет совпадения)

Синтаксис:

SELECT q.title, a.text, u.name
FROM Question q
LEFT JOIN Answer a ON q.id = a.question_id
LEFT JOIN User u ON a.user_id = u.id;

Диаграмма:

Question       Answer
┌────┐         ┌────┐
│ Q1 │    ──→  │ A1 │  (совпадение)
│ Q2 │    ──→  │ A2 │  (совпадение)
│ Q3 │    X    │ NULL │ (Q3 без ответов - будет NULL)
└────┘         └────┘

Результат: Q1-A1, Q2-A2, Q3-NULL (всё из левой!)

Визуально (диаграмма Венна):

    table1    table2
  ┌─────┬────────┐
  │LEFT │ MATCH  │
  │ +   │        │
  └─────┴────────┘

Пример результата:

title                  | text              | name
───────────────────────┼──────────────────┼───────
System Design          | Use load balancer | John
Database Optimization  | Index your data   | Jane
Network Protocols      | NULL              | NULL

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

  • Нужны все вопросы, даже без ответов
  • Поиск "несвязанных" данных (NULL в правой таблице = нет ответов)
  • Проверка целостности данных

3. RIGHT JOIN (правое внешнее соединение)

Что возвращает: ВСЕ строки из правой таблицы + совпадающие из левой (NULL если нет совпадения)

Синтаксис:

SELECT q.title, a.text
FROM Question q
RIGHT JOIN Answer a ON q.id = a.question_id;

Визуально (диаграмма Венна):

    table1    table2
  ┌────────┬────────┐
  │ MATCH  │ RIGHT  │
  │        │  +     │
  └────────┴────────┘

Пример результата:

title                  | text
───────────────────────┼──────────────────
System Design          | Use load balancer
Database Optimization  | Index your data
NULL                   | Try caching

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

  • Редко в продакшене
  • Можно переписать как LEFT JOIN с перевёрнутыми таблицами

Переписать RIGHT на LEFT:

-- Вместо этого (RIGHT JOIN):
SELECT q.title, a.text
FROM Question q
RIGHT JOIN Answer a ON q.id = a.question_id;

-- Напиши это (LEFT JOIN):
SELECT q.title, a.text
FROM Answer a
LEFT JOIN Question q ON q.id = a.question_id;

4. FULL OUTER JOIN (полное внешнее соединение)

Что возвращает: ВСЕ строки из обеих таблиц (NULL где нет совпадения)

Синтаксис:

SELECT q.title, a.text
FROM Question q
FULL OUTER JOIN Answer a ON q.id = a.question_id;

Визуально (диаграмма Венна):

    table1    table2
  ┌──────┬──────┐
  │ LEFT │RIGHT │
  │  +   │  +   │
  │ MATCH│      │
  └──────┴──────┘

Пример результата:

title                  | text
───────────────────────┼──────────────────
System Design          | Use load balancer
Database Optimization  | Index your data
Network Protocols      | NULL
NULL                   | Try caching

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

  • Сравнение данных между таблицами
  • Поиск "сирот" с обеих сторон
  • Проверка согласованности

Важно: не все БД поддерживают FULL OUTER JOIN

  • PostgreSQL: ✓ поддерживает
  • MySQL: ✗ НЕ поддерживает (эмулировать UNION)

Эмуляция FULL OUTER JOIN в MySQL:

-- PostgreSQL
SELECT * FROM Question
FULL OUTER JOIN Answer ON ...

-- MySQL (эмуляция через UNION)
SELECT * FROM Question
LEFT JOIN Answer ON ...
UNION
SELECT * FROM Answer
LEFT JOIN Question ON ...
WHERE Question.id IS NULL;

5. CROSS JOIN (декартово произведение)

Что возвращает: каждую строку из table1 скрещивает с каждой строкой из table2

Синтаксис:

SELECT p.name, s.name
FROM Profession p
CROSS JOIN Skill s;

Пример:

-- Profession: [System Analyst, Backend Developer]
-- Skill: [SQL, REST API, Caching]

Результат (2 × 3 = 6 строк):
profession           | skill
─────────────────────┼──────────────
System Analyst       | SQL
System Analyst       | REST API
System Analyst       | Caching
Backend Developer    | SQL
Backend Developer    | REST API
Backend Developer    | Caching

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

  • Генерация всех комбинаций
  • Редко в продакшене (может быть дорого!)
  • Пример: все комбинации цветов и размеров

6. SELF JOIN (соединение таблицы с самой собой)

Что возвращает: соединение таблицы саму с собой для сравнения строк

Синтаксис:

SELECT 
  c1.name AS "Child Category",
  c2.name AS "Parent Category"
FROM Category c1
LEFT JOIN Category c2 ON c1.parent_id = c2.id;

Пример:

Category (иерархия профессий):
id | name                | parent_id
───┼─────────────────────┼──────────
1  | Backend Developer   | NULL (root)
2  | Python              | 1
3  | Node.js             | 1
4  | Web Frameworks      | 3

SELF JOIN результат:
child         | parent
──────────────┼──────────────
Python        | Backend Developer
Node.js       | Backend Developer
Web Frameworks| Node.js

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

  • Иерархии (категории, сотрудник-менеджер)
  • Сравнение похожих записей
  • Поиск дубликатов

7. NATURAL JOIN

Что делает: автоматически соединяет по колонкам с одинаковыми названиями

-- Вместо явного ON
SELECT *
FROM Question
NATURAL JOIN Answer;

-- Автоматически соединит по question_id (если это колонка в обеих таблицах)

⚠️ ИЗБЕГАЙ: может привести к неожиданным результатам

  • Если добавишь новую колонку с похожим названием → JOIN сломается
  • Всегда пиши явно ON или USING

Сравнение всех JOIN'ов

TABLE1: A, B, C
TABLE2: B, C, D

                Results
INNER           B, C         (только совпадение)
LEFT            A, B, C      (всё из левой)
RIGHT           B, C, D      (всё из правой)
FULL OUTER      A, B, C, D   (всё всё всё)
CROSS           A×(B,C,D)    (все комбинации)

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

Правила оптимизации

1. Индексы на JOIN колонках

-- Эти колонки должны быть индексированы:
CREATE INDEX idx_answer_question_id ON Answer(question_id);
CREATE INDEX idx_answer_user_id ON Answer(user_id);

2. Избегай функций в JOIN условиях

-- ❌ Медленно (функция препятствует использованию индекса)
FROM Question q
JOIN Answer a ON q.id = a.question_id
WHERE LOWER(q.title) = 'system design';

-- ✓ Быстро
FROM Question q
JOIN Answer a ON q.id = a.question_id
WHERE q.title = 'System Design';

3. Порядок JOIN'ов важен

-- ✓ Хорошо: маленькие таблицы первыми
FROM Question q         -- 75k записей
JOIN Answer a ON ...    -- 500k записей
JOIN User u ON ...      -- 10k записей

-- Оптимайзер переставит, но явно указать - лучше

4. Используй EXPLAIN для анализа

EXPLAIN ANALYZE
SELECT q.title, COUNT(a.id)
FROM Question q
LEFT JOIN Answer a ON q.id = a.question_id
GROUP BY q.id;

Пример для PrepBro

-- Получить все вопросы с количеством ответов
SELECT 
  q.id,
  q.title,
  p.name AS profession,
  COUNT(a.id) AS answer_count,
  AVG(a.score) AS avg_answer_score
FROM Question q
INNER JOIN Profession p ON q.profession_id = p.id
LEFT JOIN Answer a ON q.id = a.question_id
GROUP BY q.id, q.title, p.name
ORDER BY answer_count DESC;

Разбор:

  • INNER JOIN Profession - только вопросы с профессией
  • LEFT JOIN Answer - все вопросы, даже без ответов
  • GROUP BY - агрегирование ответов

Итого

7 основных типов JOIN'ов:

JOINВозвращаетКогда
INNERСовпаденияНужны связанные данные
LEFTВсё из левойНужны все из левой
RIGHTВсё из правойРедко (переписать на LEFT)
FULLВсё из обеихСравнение, поиск сирот
CROSSПроизведениеГенерация комбинаций
SELFТаблица с собойИерархии
NATURALПо названиямИзбегай!

Правила System Analyst: ✓ Всегда определяй тип JOIN в постановке ✓ Убедись, что индексы на FK ✓ Проверь EXPLAIN ANALYZE перед отправкой ✓ Документируй, почему именно этот JOIN ✓ Помни про производительность (LEFT дороже INNER)