Уяви, що кожна таблиця у твоїй базі — це частина одного великого пазлу. Таблиця студентів знає, хто навчається, таблиця курсів — чому навчають, а таблиця записів — хто на що записаний. Але окремо ці шматочки нічого не скажуть. Хочеш побачити всю картину? Доведеться їх з'єднати — і ось тут на сцену виходить множинний JOIN.
У реальному житті дані часто організовані у зв'язані таблиці, щоб забезпечити структурованість і уникнути надлишковості. Наприклад, у нашій базі університету є такі таблиці:
students— дані про студентів.enrollments— інформація про записи студентів на курси.courses— інформація про курси.
Якщо ми хочемо отримати повний список студентів, їх курсів і викладачів, треба об'єднати три таблиці, використовуючи JOIN.
Порядок виконання JOIN
Коли використовуєш кілька JOIN, PostgreSQL обробляє їх зліва направо. Тобто спочатку об'єднуються перші дві таблиці, потім результат об'єднується з третьою таблицею, і так далі.
Приклад:
SELECT *
FROM students
INNER JOIN enrollments ON students.id = enrollments.student_id
INNER JOIN courses ON enrollments.course_id = courses.id;
- Спочатку об'єднуються таблиці
studentsіenrollmentsпо стовпцюstudents.id = enrollments.student_id. - Результат першого об'єднання використовується для об'єднання з таблицею
coursesпо стовпцюenrollments.course_id = courses.id.
Порядок виконання особливо важливий, коли у запиті беруть участь великі таблиці. Неправильна структура JOIN може призвести до суттєвого зниження продуктивності.
Приклад: Список студентів, їх курсів і викладачів
Припустимо, у нас є такі таблиці з даними:
Таблиця students:
| id | name |
|---|---|
| 1 | Otto Song |
| 2 | Maria Chi |
| 3 | Alex Lin |
Таблиця courses:
| id | name | teacher |
|---|---|---|
| 101 | Mathematics | Ellen Moore |
| 102 | Physics | James Okoro |
| 103 | Computer Science | Nina Delgado |
Таблиця enrollments:
| student_id | course_id |
|---|---|
| 1 | 101 |
| 1 | 103 |
| 2 | 102 |
| 3 | 101 |
Запит:
SELECT
students.name AS student_name,
courses.name AS course_name,
courses.teacher AS teacher_name
FROM students
INNER JOIN enrollments ON students.id = enrollments.student_id
INNER JOIN courses ON enrollments.course_id = courses.id;
Результат:
| student_name | course_name | teacher_name |
|---|---|---|
| Otto Song | Mathematics | Ellen Moore |
| Otto Song | Computer Science | Nina Delgado |
| Maria Chi | Physics | James Okoro |
| Alex Lin | Mathematics | Ellen Moore |
Фільтрація у запитах з множинними JOIN
Ти можеш застосовувати умови фільтрації до запитів з JOIN, щоб обмежити кількість повернутих даних і прискорити виконання запиту. Наприклад, якщо треба вивести тільки тих студентів, які навчаються на курсі "Mathematics":
SELECT
students.name AS student_name,
courses.name AS course_name
FROM students
INNER JOIN enrollments ON students.id = enrollments.student_id
INNER JOIN courses ON enrollments.course_id = courses.id
WHERE courses.name = 'Mathematics';
Результат:
| student_name | course_name |
|---|---|
| Otto Song | Mathematics |
| Alex Lin | Mathematics |
Оптимізація запитів з множинними JOIN
Для роботи з великими таблицями оптимізація запитів стає дуже важливою. Ось кілька порад:
- Використовуй індекси
Індекси дозволяють PostgreSQL працювати швидше, особливо при об'єднанні по ключових полях. Переконайся, що на стовпцях student_id і course_id у таблиці enrollments є індекси.
Приклад створення індексу:
CREATE INDEX idx_enrollments_student_id ON enrollments(student_id);
CREATE INDEX idx_enrollments_course_id ON enrollments(course_id);
Більше про індекси ти дізнаєшся на наступних рівнях, але все ж вирішив тут про них згадати. Вони дуже часто пов'язані з JOIN.
- Фільтруй дані на ранніх етапах
Використовуй умови WHERE, щоб зменшити кількість оброблюваних рядків до виконання JOIN. Наприклад:
SELECT
students.name AS student_name,
courses.name AS course_name
FROM students
INNER JOIN enrollments ON students.id = enrollments.student_id
INNER JOIN courses ON enrollments.course_id = courses.id
WHERE
courses.teacher = 'Ivan Petrov';
- Мінімізуй кількість рядків для об'єднання
Замість об'єднання всіх записів з двох таблиць, спробуй спочатку відфільтрувати їх підзапитами:
SELECT
students.name AS student_name,
courses.name AS course_name
FROM
(SELECT * FROM students WHERE id IN (1, 2)) sub_students
INNER JOIN enrollments ON sub_students.id = enrollments.student_id
INNER JOIN courses ON enrollments.course_id = courses.id;
Більше про вкладені SELECT ти дізнаєшся буквально на наступному рівні :P
Приклад складного об'єднання: студенти, курси і факультети
Припустимо, у нас додається ще одна таблиця faculties:
Таблиця faculties:
| id | name |
|---|---|
| 10 | Engineering |
| 20 | Natural Sciences |
Таблиця courses оновлюється:
| id | name | teacher | faculty_id |
|---|---|---|---|
| 101 | Mathematics | Ellen Moore | 10 |
| 102 | Physics | James Okoro | 20 |
| 103 | Computer Science | Nina Delgado | 10 |
Щоб отримати список студентів, курсів і факультетів, ми додаємо ще один JOIN:
SELECT
students.name AS student_name,
courses.name AS course_name,
faculties.name AS faculty_name
FROM students
INNER JOIN enrollments ON students.id = enrollments.student_id
INNER JOIN courses ON enrollments.course_id = courses.id
INNER JOIN faculties ON courses.faculty_id = faculties.id;
Результат:
| student_name | course_name | faculty_name |
|---|---|---|
| Otto Song | Mathematics | Engineering |
| Otto Song | Computer Science | Engineering |
| Maria Chi | Physics | Natural Sciences |
| Alex Lin | Mathematics | Engineering |
SQL-запити з множинними JOIN можуть бути складними, але вони дозволяють створювати потужні звіти і отримувати цінну інформацію. Якщо правильно їх оптимізувати і структурувати, вони стануть твоїм інструментом для роботи з великими базами даних.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ