JavaRush /Курсы /SQL SELF /Работа с NULL значениями при объединении да...

Работа с NULL значениями при объединении данных

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

Представьте, что вы объединяете две таблицы: students (студенты) и enrollments (записи на курсы). Если в таблице enrollments нет информации о каком-то студенте, но вы используете, например, LEFT JOIN, строки из таблицы students всё равно появятся, но информация из enrollments будет отсутствовать. Вместо конкретных данных в таких случаях появляются NULL.

Примерно так это выглядит:

Таблица students:

id name
1 Eva
2 Peter
3 Anna

Таблица enrollments:

student_id course_name
1 Математика
1 Информатика
2 Физика

Запрос с LEFT JOIN:

SELECT students.id, students.name, enrollments.course_name
FROM students
LEFT JOIN enrollments ON students.id = enrollments.student_id;

Результат:

id name course_name
1 Eva Математика
1 Eva Информатика
2 Peter Физика
3 Anna NULL

Ну, привет, NULL! Как видите, для Анны, которая не записана ни на один курс, информация о курсе отсутствует, и вместо чего-либо выводится NULL.

Как NULL влияет на запросы?

NULL — это не "ноль" и не "пустая строка", это отсутствие значения. Такое поведение имеет несколько интересных (и иногда раздражающих) последствий:

Сравнения с NULL:

Если вы напишете что-то вроде WHERE course_name = NULL, запрос не вернёт строк с NULL. Почему? Потому что с NULL нельзя сравнивать значения напрямую.

Чтобы проверить, есть ли NULL, нужно использовать специальные операторы:

WHERE course_name IS NULL

Математические операции:

Любая операция с NULL возвращает NULL. Например:

SELECT 5 + NULL; -- результат: NULL

Агрегатные функции:

SUM(), AVG(), MIN(), MAX() игнорируют NULL. COUNT(*) считает все строки независимо от содержимого колонок (он на колонки вообще не смотрит), а COUNT(column) — только те строки, где column IS NOT NULL.

Как бороться с NULL?

  1. Замена NULL на понятные значения с помощью COALESCE()

Функция COALESCE() позволяет заменить NULL другим значением. Например, если курс отсутствует, можно указать "Нет курса":

SELECT
    students.id, 
    students.name, 
    COALESCE(enrollments.course_name, 'Нет курса') AS course_name
FROM 
    students LEFT JOIN enrollments 
    ON students.id = enrollments.student_id;

Результат:

id name course_name
1 Eva Математика
1 Eva Информатика
2 Peter Физика
3 Anna Нет курса

Теперь выглядит гораздо лучше, не правда ли?

  1. Фильтрация NULL значений

Если вы не хотите видеть строки с NULL, можно использовать условие WHERE ... IS NOT NULL. Например:

SELECT
    students.id, 
    students.name, 
    enrollments.course_name
FROM 
    students LEFT JOIN enrollments 
    ON students.id = enrollments.student_id
WHERE 
    enrollments.course_name IS NOT NULL;

Результат:

id name course_name
1 Eva Математика
1 Eva Информатика
2 Peter Физика

Анна исчезает из результата, так как у неё отсутствуют записи на курсы.

  1. Считаем с учётом NULL: пример с COUNT

Как упоминалось ранее, некоторые функции игнорируют NULL, а некоторые нет. Например:

Чтобы посчитать все строки, включая те, где есть NULL:

SELECT COUNT(*) FROM students; -- Считает ВСЕ строки таблицы students, на колонки не смотрит

Чтобы посчитать только строки, где нет NULL:

SELECT COUNT(course_name) FROM enrollments;
  1. Условные выражения с CASE

Если вам не нравится COALESCE() или вы хотите больше гибкости, попробуйте использовать CASE. Например:

SELECT
    students.id, 
    students.name,
    CASE
        WHEN enrollments.course_name IS NULL THEN 'Нет курса'
        ELSE enrollments.course_name
    END AS course_name
FROM 
    students LEFT JOIN enrollments 
    ON students.id = enrollments.student_id;

Результат будет таким же, как при использовании COALESCE(), но CASE позволяет описывать более сложные правила.

  1. Используйте INNER JOIN, если уверены в отсутствии NULL

Самый радикальный способ избежать NULL — вообще не допускать их появления, используя INNER JOIN. Этот тип объединения возвращает только строки с совпадениями в обеих таблицах:

SELECT
    students.id, 
    students.name, 
    enrollments.course_name
FROM 
    students INNER JOIN enrollments 
    ON students.id = enrollments.student_id;

Без сюрпризов — только студенты, записанные на курсы.

Результат:

id name course_name
1 Eva Математика
1 Eva Информатика
2 Peter Физика

Если ваши данные требуют отображения всех значений, включая NULL, INNER JOIN не подойдёт, но иногда это всё, что нужно.

2
Задача
SQL SELF, 12 уровень, 0 лекция
Недоступна
Использование `COALESCE` для замены значений `NULL`
Использование `COALESCE` для замены значений `NULL`
2
Задача
SQL SELF, 12 уровень, 0 лекция
Недоступна
Подсчёт студентов без курсов (с использованием `COUNT`)
Подсчёт студентов без курсов (с использованием `COUNT`)
Комментарии (3)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Euraks Уровень 25
14 июня 2026
🦔
Анатолий Уровень 63
28 января 2026
❤️
Aleksandr Torhov Уровень 16
23 июля 2025
Админъ, просьба перепроверить, так как Left Join в данном случае должен вернуть все записи из таблицъ customers, а не enrollments