Ось готовий урок, створений спеціально за твоїм запитом у стилі CS50. Це поєднання енергії, чіткості та практики.
🎓 CS50-style: Урок "Subqueries (Підзапити) в SQL"
Привіт, друзі! Радий вас бачити. 👋
Сьогодні ми не просто вивчаємо "ще одну команду SQL". Сьогодні ми вчимося ставити базі даних розумні запитання. Запитання, відповідь на які залежить від... іншої відповіді.
Звучить як фільм "Початок" (Inception)? Сон уві сні? Саме так! Ми будемо занурюватися всередину запитів. Поїхали! 🚀
1. 🔥 Вступ: проблема та мотивація
Уявіть, що ви працюєте аналітиком у великому інтернет-магазині. Ваш бос прибігає до вас і каже:
"Слухай, нам терміново треба список усіх товарів, які коштують дорожче за середню ціну по магазину. Треба підняти на них маржу!"
Ви відкриваєте ноутбук, пишете SELECT * FROM products WHERE price > ... і завмираєте.
🛑 Питання до вас: А яка вона, ця "середня ціна"? Ви знаєте цю цифру прямо зараз? Ні. Я теж не знаю.
Що робить новачок?
1. Він пише запит: SELECT AVG(price) FROM products;
2. Бачить результат, наприклад, 500.
3. Копіює це число і пише другий запит: SELECT * FROM products WHERE price > 500;
У чому проблема?
Завтра привезли партію дешевих чохлів для телефонів. Середня ціна впала до 450. Ваш попередній запит із "зашитим" числом 500 тепер бреше. Він неактуальний.
Нам потрібен механізм, який сам спочатку дізнається середнє, а потім використає його для фільтрації. Все за один прохід.
Ось тут на сцену виходять Subqueries (Підзапити). Це як сказати помічнику: "Спочатку піди дізнайся ціну, а потім принеси мені список".
2. 🧠 Теоретична база (без нудьги)
Що таке Subquery?
Це запит SELECT, який живе всередині іншого запиту SELECT (або INSERT, UPDATE, DELETE).
Як це працює "під капотом"? ⚙️
Уявіть це як математичний приклад із дужками:
x = 10 + (5 * 2)
Що ми робимо спочатку? Те, що в дужках! (5 * 2) перетворюється на 10. І тільки потім ми додаємо це до зовнішнього числа.
У SQL так само: 1. Спочатку виконується внутрішній запит (те, що в дужках). 2. Його результат підставляється у зовнішній запит. 3. Виконується зовнішній запит.
🔑 Ключові моменти, які треба зрозуміти:
- Скалярний підзапит (Scalar Subquery): Повертає одне конкретне значення (одну клітинку).
- Приклад: Середня зарплата, максимальна ціна.
- Використання: З операторами
=,>,<,<>.
- Списковий підзапит (List Subquery): Повертає список значень (одну колонку, багато рядків).
- Приклад: Список ID всіх менеджерів.
- Використання: З оператором
IN.
Інтуїція: Думайте про підзапит як про змінну, значення якої база даних обчислює "на льоту" саме в ту мілісекунду, коли ви натискаєте Enter.
3. 🧪 Приклади (від простого до реального)
Для прикладів візьмемо таблицю employees (працівники):
| id | name | department | salary |
|----|-------|------------|--------|
| 1 | Ivan | IT | 2000 |
| 2 | Maria | HR | 1500 |
| 3 | Petro | IT | 2500 |
| 4 | Olya | Sales | 1200 |
Приклад №1: Скалярний підзапит
Задача: Хто заробляє більше середнього?
Спробуйте здогадатися, як це виглядатиме, перш ніж читати далі. Згадайте аналогію з дужками.
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
Розбір польотів:
1. SQL бачить дужки: (SELECT AVG(salary) FROM employees).
2. Рахує: (2000+1500+2500+1200) / 4 = 1800.
3. Підставляє це число: ... WHERE salary > 1800.
4. Видає результат: Ivan (2000) та Petro (2500).
Приклад №2: Підзапит зі списком (IN)
Уявіть, що у нас є ще таблиця departments (відділи), де є id та location.
Задача: Знайти всіх працівників, які працюють у відділах, що знаходяться в "Kyiv".
Ми не знаємо ID київських відділів. Але ми можемо їх знайти!
SELECT name
FROM employees
WHERE department_id IN (
SELECT id
FROM departments
WHERE location = 'Kyiv'
);
Що тут відбувається?
1. Внутрішній запит знаходить усі ID для Києва (наприклад, це ID 1 та 3).
2. Зовнішній запит перетворюється на: ... WHERE department_id IN (1, 3).
3. Ви отримуєте список людей. Магія! ✨
4. 🛠 Практична частина
Час розім'яти пальці! Відкрийте свій SQL-редактор (або уявіть його).
🔹 Завдання 1: Повторення — мати навчання
Напишіть запит, який знайде працівника з мінімальною зарплатою.
(Підказка: використовуйте WHERE salary = (...) і функцію MIN).
🔹 Завдання 2: "А що, якщо..."
Змініть приклад №1 так, щоб знайти тих, хто заробляє менше середнього.
🔹 Завдання 3: Виправте помилку 🐞
Студент написав такий код, щоб знайти працівників IT-відділу:
SELECT name FROM employees
WHERE department_id = (SELECT id FROM departments WHERE name = 'IT' OR name = 'Sales');
SQL видає помилку: "Subquery returns more than 1 row". Чому? І як це виправити, змінивши лише один оператор?
🔹 Завдання 4: Міні-кейс (Реальне життя)
У вас є таблиця orders (замовлення) з колонкою total_amount.
Знайдіть усі замовлення, сума яких є найбільшою серед усіх замовлень.
(Тобто, якщо максимальний чек був 5000, покажіть мені цей рядок або рядки).
5. 💡 Мислення як у розробника
Як досвідчений інженер дивиться на підзапити?
1. Типова помилка: = проти IN
Найчастіша помилка новачків (ви бачили її в завданні 3): використовувати =, коли підзапит повертає кілька рядків.
* Якщо підзапит повертає одне значення ➡️ використовуємо =, >, <.
* Якщо підзапит повертає список ➡️ використовуємо IN.
2. Читабельність чи Швидкість?
Підзапити дуже легко читати. Це як речення: "Дай мені це, де умова така...".
Але іноді (особливо на величезних базах даних) вони можуть бути повільними. Досвідчені розробники іноді переписують підзапити через JOIN, але про це пізніше.
Золоте правило: Спочатку напишіть так, щоб це було правильно і зрозуміло. Оптимізувати будете потім.
3. Алгоритм в голові
Коли я пишу складний запит, я завжди починаю з внутрішньої частини.
Я спочатку пишу SELECT AVG(salary)..., запускаю його, переконуюсь, що він працює. І тільки потім "обгортаю" його зовнішнім запитом. Не намагайтеся будувати весь будинок одразу — покладіть спочатку фундамент.
6. 🧩 Підсумок
Отже, що ми сьогодні зробили?
- Зрозуміли, що хардкодити числа — це зло.
- Навчилися вкладати запити один в один, як матрьошки 🪆.
- Освоїли скалярні підзапити (одне число) та списки (
IN).
Тепер ви вмієте: Створювати гнучкі звіти, які автоматично підлаштовуються під зміни в даних, не переписуючи код кожного разу.
🤔 Тизер наступного уроку: Підзапити — це круто, але що робити, коли нам треба вивести дані з двох таблиць одночасно поряд (наприклад, Ім'я працівника і Назву його відділу)? Вкладеність тут не допоможе. Тут нам знадобиться найпотужніша зброя SQL — JOIN. Готуйтеся з'єднувати світи!
А поки що — практикуйтеся! Це був CS50... тобто, ваш урок SQL. Побачимось! 💻