Модуль 14

JOIN-и та складні запити

Ось готовий урок, згенерований у стилі CS50, спеціально для тебе.


🎓 CS50: JOIN-и та мистецтво поєднання даних

Привіт, друзі! Мене звати [Твоє Ім'я], і це... CS50: SQL Edition.

Сьогодні ми не просто пишемо код. Сьогодні ми вчимося бути цифровими детективами. Ми будемо зв’язувати докази, шукати відповідності та будувати повну картину світу з розрізнених шматочків.

Тема нашого уроку: JOIN-и (Об'єднання таблиць).


1. 🔥 Вступ: Проблема «Розірваного блокнота»

Уявіть, що ви керуєте популярним інтернет-магазином кросівок.

У вас є Excel-таблиця №1, де записані ваші клієнти: * ID клієнта * Ім'я * Email

І є Excel-таблиця №2, де записані замовлення: * ID замовлення * ID клієнта (хто купив) * Сума покупки

Ситуація: Вам потрібно зателефонувати кожному, хто зробив замовлення на суму понад 5000 грн.

Проблема: У таблиці замовлень є сума, але немає імені та телефону. Там лише сухе число user_id = 42. Хто такий 42? Ви дивитесь у першу таблицю, шукаєте рядок 42, копіюєте телефон... Потім берете наступне замовлення... і знову шукаєте.

Риторичне запитання: Ви справді хочете робити це вручну для 10 000 замовлень? Звісно, ні!

Навіщо це потрібно: У базах даних ми навмисно розділяємо дані (нормалізація), щоб не дублювати інформацію. Але коли нам потрібен звіт, ми мусимо зібрати ці дані назад в єдине ціле. Ось тут на сцену виходить JOIN.

Аналогія: Уявіть дошку детектива у фільмі. Зліва — фото підозрюваних (таблиця Users). Справа — місця злочину (таблиця Orders). JOIN — це та червона нитка, якою детектив з'єднує фото з місцем події.


2. 🧠 Теоретична база: Як працює магія з'єднання

Давайте заглянемо «під капот».

Коли ви кажете базі даних: "З'єднай мені Клієнтів та Замовлення", вона запитує: "А за якою ознакою?" Це ключовий момент. Вам потрібен спільний знаменник. Зазвичай це Foreign Key (Зовнішній ключ).

Головні типи JOIN-ів (запам'ятайте ці два!)

Ми часто малюємо це як діаграми Венна (кола, що перетинаються), але давайте простіше:

  1. INNER JOIN (Внутрішнє об'єднання) — "Сувора вечірка".

    • Тут зустрічаються лише ті, хто є в обох списках.
    • Якщо є Клієнт без Замовлення — його не буде у результаті.
    • Якщо є Замовлення без Клієнта (дивний баг, але буває) — його теж не буде.
    • Результат: Тільки пари, що ідеально співпали.
  2. LEFT JOIN (Ліве об'єднання) — "Інклюзивна вечірка".

    • Ми беремо ВСІХ з лівої таблиці (Клієнти).
    • І намагаємося підібрати їм пару з правої (Замовлення).
    • Якщо замовлення є — чудово, показуємо дані.
    • Якщо замовлення немає — база даних не видаляє клієнта, а пише навпроти нього NULL (порожнеча).
    • Результат: Всі клієнти + інформація про їхні покупки (якщо вони були).

Інтуїтивне розуміння: * INNER JOIN звужує результат (відсікає зайве). * LEFT JOIN зберігає масштаб головної таблиці.


3. 🧪 Приклади: Від простого до реального

У нас є дві маленькі таблиці.

users (користувачі): | id | name | |----|-------| | 1 | Тарас | | 2 | Леся | | 3 | Іван |

orders (замовлення): | id | user_id | product | |----|---------|---------| | 101| 1 | Ноутбук | | 102| 1 | Мишка | | 103| 2 | Книга |

(Зверніть увагу: Іван (id=3) нічого не купив).

Приклад 1: INNER JOIN

Ми хочемо отримати список покупок з іменами покупців.

Запитання до вас: Чи побачимо ми Івана у цьому списку?

SELECT users.name, orders.product
FROM users
INNER JOIN orders ON users.id = orders.user_id;

Результат: | name | product | |-------|---------| | Тарас | Ноутбук | | Тарас | Мишка | | Леся | Книга |

Пояснення: Івана немає. INNER JOIN викинув його, бо у нього немає пари в таблиці orders. Тарас з'явився двічі, бо зробив два замовлення.


Приклад 2: LEFT JOIN

Ми хочемо побачити звіт по всіх клієнтах, щоб зрозуміти, хто активний, а хто ні.

Запитання до вас: Що буде навпроти імені Іван у колонці товарів?

SELECT users.name, orders.product
FROM users
LEFT JOIN orders ON users.id = orders.user_id;

Результат: | name | product | |-------|---------| | Тарас | Ноутбук | | Тарас | Мишка | | Леся | Книга | | Іван | NULL |

Пояснення: База даних взяла Івана, спробувала знайти замовлення, не знайшла, і дбайливо поставила NULL. Тепер ми бачимо повну картину.


Приклад 3: Складний запит (Реальне життя)

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

SELECT 
    users.name, 
    SUM(products.price) as total_spent
FROM users
INNER JOIN orders ON users.id = orders.user_id
INNER JOIN products ON orders.product_id = products.id
GROUP BY users.name;

Логіка: 1. Беремо юзера. 2. Приєднуємо його замовлення. 3. До кожного замовлення "підтягуємо" ціну з таблиці товарів. 4. Групуємо по імені та сумуємо ціни.


4. 🛠 Практична частина

Прийшов час забруднити руки кодом! Відкрийте ваш редактор SQL (або уявіть його).

Завдання 1 (Повторення): Перепишіть INNER JOIN з прикладу 1, але додайте у вибірку ще й orders.id (номер замовлення).

Завдання 2 (Експеримент): У запиті з LEFT JOIN (приклад 2) поміняйте місцями таблиці: напишіть FROM orders LEFT JOIN users. Питання: Чи зникне Іван? Чому? (Спробуйте передбачити результат до запуску).

Завдання 3 (Детектив): Знайдіть користувачів, які нічого не купили. Підказка: Використовуйте LEFT JOIN і додайте умову WHERE orders.id IS NULL. Це супер-популярний патерн на співбесідах!

Завдання 4 (Виправлення помилки): Студент написав такий код і сервер "завис":

SELECT * FROM users JOIN orders;

Він забув ON .... Що сталося? (Гугліть "Cartesian Product SQL", якщо не знаєте).

Завдання 5 (Міні-кейс): Є таблиця Students (Студенти) і Courses (Курси). Створіть запит, який покаже, які курси відвідує кожен студент. Врахуйте, що один студент може ходити на багато курсів.


5. 💡 Мислення як у розробника

Ось що відрізняє новачка від профі в роботі з JOIN-ами:

  1. Аліаси (Псевдоніми) — ваші друзі. Новачок пише: users.name, orders.id. Профі пише: sql FROM users AS u JOIN orders AS o ON u.id = o.user_id Це економить час і робить код читабельним.

  2. Завжди думайте про NULL. Коли ви робите LEFT JOIN, ви гарантовано створюєте потенційні NULL. Якщо ви потім спробуєте зробити математичну операцію з NULL (наприклад, 5 + NULL), результат буде NULL. Профі завжди це обробляють (функція COALESCE або IFNULL).

  3. Не бійтеся кількох JOIN-ів. У реальних проєктах (Amazon, Facebook) доводиться з'єднувати 5, 10, а то й 20 таблиць. Головне — не загубити нитку логіки: Таблиця А зв'язана з Б, Б зв'язана з В, В зв'язана з Г.


6. 🧩 Підсумок

Отже, що ми сьогодні зробили? Ми відмовилися від ручного пошуку у двох таблицях і навчили базу даних робити це за нас.

  • Ви знаєте, що INNER JOIN — це перетин (тільки спільне).
  • Ви знаєте, що LEFT JOIN — це збереження всього з лівої таблиці (навіть без пари).
  • Ви розумієте, що без ON трапиться катастрофа.

Що ви тепер вмієте: Ви можете брати розрізнені дані та перетворювати їх на корисну інформацію для бізнесу. Ви більше не бачите просто таблиці, ви бачите зв'язки.

Наступного разу: Ви спитаєте: "Девіде, а якщо в таблиці мільйон рядків, чи не буде JOIN працювати вічність?" Чудове питання! Це підводить нас до теми Індексів (Indexes) — як змусити базу даних шукати дані зі швидкістю світла.

А поки що... це був CS50. Щасти вам з кодом!