На минулій лекції ми обговорили, які типи JOIN бувають у SQL. Сьогодні детальніше зупинимось на INNER JOIN.
INNER JOIN — це тип об'єднання даних у реляційних базах, який дозволяє взяти рядки з двох таблиць і повернути тільки ті рядки, які "співпадають" згідно з визначеною тобою умовою. Тобто, INNER JOIN повертає лише перетин двох таблиць, ігноруючи все інше.
Давай уявимо, що в тебе є дві коробки. В одній лежать картки зі студентами, а в іншій — картки з курсами, на які зареєстровані студенти. Ти хочеш дізнатись, які студенти записані на які курси. Якщо немає співпадіння (наприклад, студент ніде не записаний), ці дані нас поки не цікавлять. Такий сценарій ідеально підходить для INNER JOIN.
Синтаксис INNER JOIN
Синтаксис досить прямолінійний — ти вказуєш дві таблиці, які хочеш об'єднати, і задаєш умову об'єднання через ключове слово ON.
SELECT стовпці
FROM таблиця1 INNER JOIN таблиця2
ON таблиця1.поле = таблиця2.поле;
таблиця1ітаблиця2— це таблиці, які ти хочеш об'єднати.поле— це стовпці, за якими йде співставлення.- Умова після
ONзадає правила співставлення рядків з обох таблиць.
Приклади використання INNER JOIN
Для подальших прикладів ми будемо працювати з двома таблицями:
Таблиця students — дані про студентів
| student_id | name | age |
|---|---|---|
| 1 | Otto | 20 |
| 2 | Anna | 22 |
| 3 | Peter | 19 |
| 4 | Dia | 21 |
Таблиця enrollments — дані про записи на курси
| enrollment_id | student_id | course_id |
|---|---|---|
| 101 | 1 | 501 |
| 102 | 2 | 502 |
| 103 | 2 | 503 |
| 104 | 3 | 504 |
Зверни увагу, що студентка Dia (з student_id = 4) не зареєстрована ні на один курс.
Приклад 1: Отримання записів про студентів і їх курси
Ми хочемо дізнатись, які студенти записані на курси. Це типовий приклад використання INNER JOIN. Нас цікавить тільки те, де є співпадіння даних між таблицями students і enrollments на основі student_id.
SELECT students.name, enrollments.course_id
FROM students INNER JOIN enrollments
ON students.student_id = enrollments.student_id;
Результат:
| name | course_id |
|---|---|
| Otto | 501 |
| Anna | 502 |
| Anna | 503 |
| Peter | 504 |
Що ми бачимо? INNER JOIN повернув тільки тих студентів, які зареєстровані на курси. Студентка Dia, яка ніде не записана, залишилась за бортом.
Приклад 2: Отримання замовлень і клієнтів
Тепер давай розглянемо інший приклад. Нехай у нас є таблиці orders (замовлення) і customers (клієнти). Ми хочемо отримати список усіх замовлень з іменами клієнтів.
Таблиця orders
| order_id | customer_id | amount |
|---|---|---|
| 1 | 101 | 500 |
| 2 | 102 | 300 |
| 3 | 103 | 700 |
Таблиця customers
| customer_id | name |
|---|---|
| 101 | Otto |
| 102 | Anna |
| 104 | Peter |
Задача: нам треба об'єднати orders і customers по customer_id, щоб повернути тільки ті замовлення, у яких є відповідний клієнт.
SELECT orders.order_id, customers.name, orders.amount
FROM orders INNER JOIN customers
ON orders.customer_id = customers.customer_id;
Результат:
| order_id | name | amount |
|---|---|---|
| 1 | Otto | 500 |
| 2 | Anna | 300 |
Зверни увагу, що замовлення з order_id = 3 не потрапило в результат, бо клієнта з customer_id = 103 немає в таблиці customers.
Як INNER JOIN допомагає з'єднувати таблиці (і що може піти не так)
INNER JOIN — це основний інструмент, який ти будеш юзати майже в будь-якому проєкті, де є реляційна база даних. Це як гайковий ключ у наборі інструментів: можна спробувати обійтись без нього, але буде набагато складніше досягти результату. Наприклад:
- Коли створюєш звіти, де треба комбінувати дані з кількох таблиць.
- Для побудови аналітики, коли треба з'єднати факти з вимірами (наприклад, продажі і клієнти).
- Для інтеграції даних сторонніх систем.
Найчастіша помилка новачків — забутий ON або неправильно вказана умова об'єднання. Якщо не задати правильну умову, то замість очікуваного результату ти отримаєш декартовий добуток двох таблиць — це може бути тисячі або мільйони рядків, які не мають сенсу.
Приклад помилки:
У цьому прикладі немає умови об'єднання, тому запит створить кожну можливу комбінацію рядків з двох таблиць (і це, скоріш за все, не те, що тобі потрібно):
SELECT students.name, enrollments.course_id
FROM students, enrollments; -- ПОМИЛКА: немає умови об'єднання!
Результат буде виглядати як хаос: кожен рядок students поєднується з кожним рядком enrollments.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ