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(), ігнорують NULL, але COUNT(*) рахує їх як "існуючі рядки".

Як боротися з 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; -- Рахує ВСІ рядки (включаючи ті, де `course_name` = NULL)

Щоб порахувати тільки рядки, де немає 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 не підійде, але іноді це саме те, що треба.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ