Ось готовий урок, створений спеціально за твоїм майстер-промптом. Вмикаємо "режим Малана" — енергія, чіткість і фокус на розумінні суті. 🚀
🎓 Урок: Aggregate Functions та GROUP BY
(Або як перетворити мільйон рядків на три зрозумілі цифри)
1. 🔥 Вступ: Проблема та мотивація
Уявіть, що ви — власник величезної мережі кав’ярень, скажімо, "Global Coffee". У вас є база даних, і в ній — таблиця orders. Щодня там з’являються тисячі нових записів:
* ID: 1054, Кава: Лате, Ціна: 60 грн, Місто: Київ
* ID: 1055, Кава: Еспресо, Ціна: 40 грн, Місто: Львів
* ...і так далі, мільйон рядків.
Я заходжу до вашого кабінету і питаю: "Скільки грошей ми заробили сьогодні у Львові?"
Що ви будете робити? 1. Вивантажите всі мільйон рядків у Excel? 2. Будете гортати їх вручну і додавати на калькуляторі? 3. Чи, можливо, скажете мені: "Зачекай тиждень, я порахую"?
Це не працює. Дані (raw data) самі по собі — це просто шум. Нам потрібна інформація. Нам не потрібен список чеків. Нам потрібна сума. Нам не потрібен перелік клієнтів, нам потрібна їхня кількість.
Саме тут на сцену виходять Агрегатні функції та магічна команда GROUP BY. Це інструменти, які перетворюють "гори сміття" на аналітику, на основі якої приймаються бізнес-рішення на мільярди доларів.
Без цього ви просто бібліотекар, який знає, де лежать книги. З цим — ви аналітик, який знає, що читають люди.
2. 🧠 Теоретична база (без сухої академічності)
Давайте розберемося, що відбувається "під капотом".
Агрегатні функції
Уявіть блендер. Ви кидаєте туди цілу купу фруктів (рядків даних), натискаєте кнопку, і на виході отримуєте один однорідний смузі (одне число).
Ось ваші "кнопки" на блендері:
* COUNT() — Рахівник. Скільки всього елементів? (Скільки чеків?)
* SUM() — Калькулятор. Яка сума значень? (Скільки всього грошей?)
* AVG() — Середнє. Який середній чек?
* MAX() / MIN() — Крайнощі. Яка найдорожча покупка? Яка найдешевша?
GROUP BY (Групування)
Але що, якщо я хочу смузі окремо з полуниці і окремо з бананів? Мені треба розкласти фрукти по різних мисках перед тим, як кидати їх у блендер.
GROUP BY — це сортувальник.
Коли ви пишете GROUP BY city, база даних робить наступне:
1. Пробігає по всіх рядках.
2. Бачить "Київ" — кидає в кошик "Київ".
3. Бачить "Львів" — кидає в кошик "Львів".
4. І тільки потім застосовує агрегатну функцію (наприклад, SUM) окремо до кожного кошика.
❗️ Що треба запам’ятати залізно:
Якщо ви використовуєте GROUP BY, то у вашому SELECT можуть бути лише два типи речей:
1. Те, по чому ви групуєте (назва кошика).
2. Агрегатні функції (результат обробки кошика).
Все інше — заборонено. Ви не можете запитати "Який ID замовлення?", якщо ви згрупували по містах. Чому? Бо в кошику "Київ" тисячі ID. Який саме ви хочете? База даних не знає і видасть помилку.
3. 🧪 Приклади (від простого до реального)
У нас є таблиця sales:
| id | product | category | amount | city |
|---|---|---|---|---|
| 1 | iPhone | Electronics | 1000 | Kyiv |
| 2 | Jeans | Clothing | 50 | Lviv |
| 3 | Laptop | Electronics | 1500 | Kyiv |
| 4 | T-shirt | Clothing | 20 | Kyiv |
| 5 | Mouse | Electronics | 30 | Lviv |
Приклад 1: Проста агрегація
Завдання: Скільки всього грошей ми заробили?
SELECT SUM(amount)
FROM sales;
Результат: 2600
Пояснення: Блендер змолов усе в одне число.
Приклад 2: GROUP BY
Завдання: Я хочу знати виручку по кожній категорії товарів окремо. Що ви очікуєте побачити? Таблицю, де є назва категорії і сума.
SELECT category, SUM(amount) as total_revenue
FROM sales
GROUP BY category;
Результат: | category | total_revenue | | :--- | :--- | | Electronics | 2530 | | Clothing | 70 |
Пояснення: SQL розділив рядки на купки "Electronics" і "Clothing", а потім просумував amount у кожній купці.
Приклад 3: GROUP BY + HAVING (Фільтрація груп)
Завдання: Покажи тільки ті категорії, де ми заробили більше 1000 доларів.
Тут новачок часто пише WHERE. Але WHERE працює з рядками (до групування). А нам треба відфільтрувати результат (після групування). Для цього є HAVING.
SELECT category, SUM(amount) as total_revenue
FROM sales
GROUP BY category
HAVING SUM(amount) > 1000;
Результат: | category | total_revenue | | :--- | :--- | | Electronics | 2530 |
Пояснення: "Clothing" відпав, бо 70 < 1000. HAVING — це як фейс-контроль, який стоїть після того, як групи сформовані.
4. 🛠 Практична частина
Припустимо, у нас є таблиця students:
(id, name, faculty, gpa, year_of_study)
Виконай ці завдання подумки або у редакторі коду:
- 🔹 Розігрів: Порахуй загальну кількість студентів у таблиці.
- 🔹 Класика: Знайди середній бал (
AVG(gpa)) для кожного факультету (faculty). - 🔹 Уважність: Порахуй, скільки студентів навчається на кожному курсі (
year_of_study), але відсортуй результат від найменшого курсу до найбільшого. - 🔹 Виправ помилку:
sql SELECT name, count(*) FROM students GROUP BY faculty;Чому цей код впаде з помилкою? Що треба змінити? - 🔹 Міні-кейс: Ректор хоче нагородити факультети-відмінники. Виведи список факультетів, де середній бал (
gpa) вищий за 4.5. (Підказка: використовуйHAVING). - 🔹 А що, якщо... Тобі треба знайти максимальний бал (
MAX(gpa)) серед студентів 1-го курсу. Тобі треба спочатку відфільтрувати першокурсників (WHERE) чи спочатку згрупувати? Подумай про логіку.
5. 💡 Мислення як у розробника
Як думає досвідчений розробник, коли пише такі запити?
-
Порядок виконання (Order of Execution). Це найважливіший секрет. Ви пишете:
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING. Але база даних читає це так:FROM(Звідки беремо дані?)WHERE(Відфільтрувати зайві рядки до групування).GROUP BY(Розкласти по кошиках).HAVING(Відкинути непотрібні кошики).SELECT(Показати результат). Розуміння цього порядку рятує від 90% помилок.
-
Пастка
COUNT(*)протиCOUNT(column_name).COUNT(*)рахує всі рядки, навіть якщо там NULL.COUNT(email)порахує тільки тих, у кого заповнений email. Завжди питайте себе: "Мені треба порахувати людей чи заповнені анкети?"
-
Оптимізація. Групувати по текстовому полю (назва міста) повільніше, ніж по ID (id міста). Якщо у вас мільйони рядків, завжди групуйте по
city_id, а назву підтягуйте пізніше.
6. 🧩 Підсумок
Сьогодні ми навчилися не просто дивитися на дані, а бачити їх структуру.
- Ви знаєте, як стиснути мільйон рядків у корисну статистику (
Aggregate functions). - Ви вмієте розбивати дані на логічні сегменти (
GROUP BY). - Ви вмієте фільтрувати ці сегменти (
HAVING).
Тепер ви можете відповісти на питання бізнесу: "Де ми втрачаємо гроші?", "Хто наш найкращий клієнт?", "Який середній вік нашого користувача?".
👀 Що далі? Зараз ми працювали з однією таблицею. Але в реальному житті замовлення лежать в одній таблиці, а імена клієнтів — в іншій. Як з’єднати їх разом, щоб дізнатися, хто саме купив цей дорогий ноутбук? Наступного разу ми поговоримо про найпотужнішу зброю SQL — JOIN.
А поки що — практикуйтеся!