JavaRush /Курси /SQL SELF /Типові помилки при використанні JOIN

Типові помилки при використанні JOIN

SQL SELF
Рівень 12 , Лекція 4
Відкрита

Тепер настав час поговорити про життя. Про ту його сторону, якої не уникнути: помилки. Ловити, виправляти і розуміти помилки — це обов'язкова частина роботи з даними. Давай розберемо, на які граблі можна наступити при роботі з JOIN в SQL, і як їх обійти.

Помилка 1: Пропуск умови з'єднання — створення декартового добутку

Найчастіша помилка — забути вказати умову з'єднання, використовуючи ON. У такому випадку виникає декартовий добуток, коли кожен рядок з першої таблиці з'єднується з кожним рядком з другої. В результаті ти отримуєш купу рядків, які не мають жодного сенсу і тільки збивають з пантелику.

Ось приклад. Припустимо, у нас є такі таблиці:

Студенти (students):

student_id name
1 Otto
2 Anna

Курси (courses):

course_id course_name
101 Математика
102 Історія

Тепер напишемо запит, забувши про ON:

SELECT *
FROM students
JOIN courses;

Результат:

student_id name course_id course_name
1 Otto 101 Математика
1 Otto 102 Історія
2 Anna 101 Математика
2 Anna 102 Історія

Не схоже на правду, так? Цей жах називається декартовим добутком.

Як виправити: використовуй ON, щоб вказати, як пов'язані дані в таблицях.

SELECT *
FROM students
JOIN courses
ON students.student_id = courses.course_id;

І тут з'являється новий розділ помилки...

Захист від дурня

Це настільки поширена проблема, що в PostgreSQL заборонили використання JOIN без ON та умови.

Якщо тобі треба об'єднати кожен рядок з кожним, можна використати синтаксис без JOIN:

SELECT *
FROM students, courses;

Ще варіант 3 варіант - коли JOIN без ON працює:

  • З NATURAL JOIN — автоматично підбирає однакові за назвою колонки.
  • З USING — вказуєш список колонок, по яких об'єднуються колонки.
  • CROSS JOIN — завжди без умови - те ж саме, що і декартовий добуток.

Помилка 2: Невірна умова з'єднання

Іноді ти вказуєш умову з'єднання, але робиш це неправильно. Наприклад, з'єднуєш таблиці не по ключах, а по нерелевантних даних.

Припустимо, ми хочемо отримати список студентів і курсів, на які вони записані, але помиляємось і з'єднуємо таблиці по невідповідних полях:

SELECT *
FROM students
JOIN courses
ON students.student_id = courses.course_id;

Такий запит призведе до некоректного результату, бо student_id і course_id — це зовсім різні речі.

Як виправити: переконайся, що використовуєш правильні стовпці для з'єднання. Правильне об'єднання може виглядати так (якщо у тебе є таблиця enrollments, що зв'язує студентів з курсами):

SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;

Помилка 3: Дублювання рядків у результаті

Коли ти додаєш кілька JOIN у запит, іноді це призводить до дублювання рядків. Це трапляється, якщо в таблицях JOIN є повторювані записи, або ти неправильно вказав умови об'єднання.

Припустимо, студент Otto двічі записаний на один і той самий курс у таблиці enrollments.

Записи в enrollments:

student_id course_id
1 101
1 101

Тепер запит з JOIN дасть такі результати:

SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;

Результат:

name course_name
Otto Математика
Otto Математика

Як виправити: по-перше, переконайся, що у твоїх таблицях немає дублюючих даних. По-друге, якщо це очікувана поведінка, видаляй дублікати за допомогою DISTINCT:

SELECT DISTINCT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;

Помилка 4: Втрата рядків при використанні INNER JOIN

INNER JOIN повертає тільки ті рядки, які збігаються в обох таблицях. Якщо в одній з таблиць немає відповідного значення, рядок буде відкинутий. Ти можеш втратити дані, якщо неправильно вибереш тип з'єднання.

Припустимо, у нас є студент, який ще не записаний ні на один курс:

Студенти (students):

student_id name
1 Otto
2 Anna
3 Dhany

Записи (enrollments):

student_id course_id
1 101
2 102

Тепер запит з INNER JOIN:

SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;

Результат:

name course_name
Otto Математика
Anna Історія

А де Dhany? Якщо ти хочеш включити студентів без курсів, треба використовувати LEFT JOIN:

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

Помилка 5: Неправильна обробка NULL значень

Якщо в одній з таблиць є рядки з порожніми (NULL) значеннями, вони можуть не потрапити у результати (наприклад, при використанні умов фільтрації).

Приклад: ти використовуєш LEFT JOIN, але потім додаєш WHERE для фільтрації.

SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id
WHERE courses.course_name = 'Математика';

Тепер студенти без курсів не потраплять у результат, навіть якщо ти використав LEFT JOIN.

Як виправити: якщо хочеш включити рядки з відсутніми курсами, заміни WHERE на ON або додай додаткову умову:

SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id
WHERE courses.course_name IS NULL OR courses.course_name = 'Математика';

Помилка 6: Плутанина між типами з'єднань

Ти плутаєшся, який тип з'єднання використовувати. Наприклад, застосовуєш RIGHT JOIN, хоча можна було б скористатися LEFT JOIN, просто помінявши порядок таблиць.

Як уникнути плутанини:

  • Використовуй LEFT JOIN, якщо можеш. Це більш інтуїтивно зрозуміло.
  • Зміни порядок таблиць, щоб не довелося використовувати RIGHT JOIN.
1
Опитування
Множинні JOIN, рівень 12, лекція 4
Недоступний
Множинні JOIN
Множинні JOIN
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ