JavaRush /Курсы /SQL SELF /Полное объединение данных с FULL OUTER JOIN

Полное объединение данных с FULL OUTER JOIN

SQL SELF
11 уровень , 4 лекция
Открыта

Сегодня мы разберёмся с самой демократичной формой объединения данных — FULL OUTER JOIN. Это объединение, где все желающие попадают в результат, даже если у них нет пары.

FULL OUTER JOIN — это вид объединения данных, где возвращаются все строки из обеих таблиц. Если для строки в одной таблице нет соответствующей строки в другой, вместо отсутствующих значений в результирующий набор записываются NULL. Это как вести учет всех людей, которые пришли на две разные вечеринки: даже если кто-то пришёл только на одну из них, он всё равно будет учтён.

Визуально это можно представить так:

Таблица A                     Таблица B
+----+----------+             +----+----------+
| id | name     |             | id | course   |
+----+----------+             +----+----------+
| 1  | Alice    |             | 2  | Math     |
| 2  | Bob      |             | 3  | Physics  |
| 4  | Charlie  |             | 5  | History  |
+----+----------+             +----+----------+

FULL OUTER JOIN РЕЗУЛЬТАТ:
+----+----------+----------+
| id | name     | course   |
+----+----------+----------+
| 1  | Alice    | NULL     |
| 2  | Bob      | Math     |
| 3  | NULL     | Physics  |
| 4  | Charlie  | NULL     |
| 5  | NULL     | History  |
+----+----------+----------+

Строки без соответствия сохраняются, но данные для отсутствующих колонок будут заполнены значением NULL.

Синтаксис FULL OUTER JOIN

Синтаксис выглядит просто, но мощь его велика:

SELECT
    столбцы
FROM 
    таблица1
FULL OUTER JOIN 
    таблица2
ON таблица1.общий_столбец = таблица2.общий_столбец;

Ключевая часть здесь — FULL OUTER JOIN, которая заставляет PostgreSQL взять все строки из обеих таблиц. Если для какой-то строки не хватает пары по условию ON, значения заменяются на NULL.

Примеры использования

Давайте разберем реальные примеры на основе хорошо знакомой базы данных university с таблицами students и enrollments.

Пример 1: список всех студентов и курсов

Представьте, что у нас есть две таблицы:

Таблица students:

student_id name
1 Alice
2 Bob
3 Charlie

Таблица enrollments:

enrollment_id student_id course
101 1 Math
102 2 Physics
103 4 History

Наша задача — составить полный список студентов и курсов, включая тех студентов, которые не записаны ни на один курс, и курсы без студентов.

Вот запрос:

SELECT
    s.student_id, 
    s.name, 
    e.course
FROM 
    students s
FULL OUTER JOIN 
    enrollments e
ON 
    s.student_id = e.student_id;

Результат:

student_id name course
1 Alice Math
2 Bob Physics
3 Charlie NULL
NULL NULL History

Как видите, в результат попали все студенты и все курсы. Студент Charlie не записан на курсы, поэтому для него поле courseNULL. А курс History не имеет студента, поэтому его student_id и name равны NULL.

Пример 2: Анализ продаж и товаров

Теперь подумаем о магазине. У нас есть две таблицы:

Таблица products:

product_id name
1 Laptop
2 Smartphone
3 Printer

Таблица sales:

sale_id product_id quantity
101 1 5
102 3 2
103 4 10

Мы хотим получить полный список всех продуктов и продаж, включая те продукты, которые не были проданы, и продажи с неверными идентификаторами product_id.

Запрос:

SELECT
    p.product_id,
    p.name AS product_name,
    s.quantity
FROM 
    products p
FULL OUTER JOIN 
    sales s
ON 
    p.product_id = s.product_id;

Результат:

product_id product_name quantity
1 Laptop 5
2 Smartphone NULL
3 Printer 2
NULL NULL 10

Здесь мы видим, что у Smartphone продаж не было (quantity = NULL), а продажа с product_id = 4 не соответствует ни одному продукту.

Практическое задание

Попробуйте написать запрос для таблиц departments и employees:

Таблица departments:

department_id department_name
1 HR
2 IT
3 Marketing

Таблица employees:

employee_id department_id name
101 1 Alice
102 2 Bob
103 4 Charlie

Напишите FULL OUTER JOIN, чтобы получить полный список департаментов и сотрудников. Заполните отсутствующие данные строками с NULL.

Как обработать NULL значения

Проблема NULL значений — это неизбежное последствие использования FULL OUTER JOIN. Например, в реальных задачах вам может понадобиться заменять NULL на более осмысленные значения. В PostgreSQL это можно сделать с помощью функции COALESCE().

Пример:

SELECT
    COALESCE(s.name, 'No Student') AS student_name,
    COALESCE(e.course, 'No Course') AS course_name
FROM 
    students s
FULL OUTER JOIN 
    enrollments e
ON 
    s.student_id = e.student_id;

Результат:

student_name course_name
Alice Math
Bob Physics
Charlie No Course
No Student History

Теперь вместо NULL мы видим понятные значения, которые делают отчеты более читаемыми.

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

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

  • Отчеты по продажам и товарам — чтобы увидеть как проданные, так и непроданные товары.
  • Анализ студентов и курсов — чтобы проверить, есть ли неучтенные данные.
  • Сравнение списков — например, для выявления несоответствий между двумя наборами данных.

Надеюсь эта лекция дала вам хорошее представление о FULL OUTER JOIN. Теперь вас ждёт увлекательный мир более сложных объединений и обработки данных!

2
Задача
SQL SELF, 11 уровень, 4 лекция
Недоступна
Использование FULL OUTER JOIN для объединения данных
Использование FULL OUTER JOIN для объединения данных
2
Задача
SQL SELF, 11 уровень, 4 лекция
Недоступна
Сравнение студентов и курсов используя FULL OUTER JOIN
Сравнение студентов и курсов используя FULL OUTER JOIN
1
Опрос
Объединение данных, 11 уровень, 4 лекция
Недоступен
Объединение данных
Объединение данных
Комментарии (7)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Анатолий Уровень 50
28 января 2026
😎
Anonymous #2820389 Уровень 15
4 сентября 2025
Что произойдёт, если забыть указать условие ON в запросе с JOIN? Правильный ответ: Запрос не выполнится. Запрос SELECT * FROM authors JOIN books; Приведет к [42601] ERROR: syntax error at end of input Для получения декартова произведения необходимо использовать запрос без JOIN SELECT * FROM authors, books; Официальная документация https://postgrespro.ru/docs/postgrespro/current/tutorial-join Или SELECT * FROM authors CROSS JOIN books; SELECT * FROM authors JOIN books ON TRUE; https://postgrespro.ru/docs/postgrespro/current/queries-table-expressions
25 июня 2025
Во второй задаче без CASCADE не обойтись

DROP TABLE IF EXISTS students CASCADE ;
Slevin Уровень 57
4 сентября 2025
О, спасибо за метод, а то пришлось в ручную писать удаление и зависимой таблицы.
Hayk Kocharyan Уровень 36
23 октября 2025
можно очень легким путем select student_id, name, course_name from students FULL OUTER JOIN courses on students.student_id = courses.student_id
Vlad Tagunkov Уровень 10
26 декабря 2025
уже почти Январь - а это так и не починили
Anton Zhukov Уровень 12
25 июня 2025
Error executing SQL statement. ОШИБКА: удалить объект таблица students нельзя, так как от него зависят другие объекты Detail: ограничение enrollments_student_id_fkey в отношении таблица enrollments зависит от объекта таблица students Hint: Для удаления зависимых объектов используйте DROP ... CASCADE. - Connection: postgres@localhost: 104ms