Уяви, що ти працюєш аналітиком в університеті (ми ж робимо базу даних для університету, пам’ятаєш?). Тебе попросили не просто вивести студентів і їхні оцінки, а додати в таблицю стовпець з максимальною оцінкою в групі, щоб легко порівнювати результати. Як вирішити цю задачу? Звісно, за допомогою підзапитів у SELECT!
Підзапит у SELECT дозволяє обчислювати значення прямо під час виконання основного запиту. Це круто, бо ти можеш комбінувати агреговані розрахунки, складні фільтри й навіть іншу колекцію даних в одному запиті.
Основи вкладених запитів у SELECT
Підзапит у SELECT буквально працює так, як звучить: ти вставляєш результат одного SELECT всередину іншого. Це дозволяє розрахувати додаткові значення для кожного рядка результату.
Ось простий приклад. Припустимо, у нас є таблиця students з такою структурою:
| student_id | name | group_id |
|---|---|---|
| 1 | Linda | 101 |
| 2 | Otto | 102 |
| 3 | Anna | 101 |
І таблиця grades:
| grade_id | student_id | grade |
|---|---|---|
| 1 | 1 | 5 |
| 2 | 1 | 4 |
| 3 | 2 | 3 |
| 4 | 3 | 5 |
| 5 | 3 | 4 |
Приклад 1: Додавання максимальної оцінки в групі
Задача: вивести імена студентів, їхні оцінки та максимальну оцінку в групі, щоб було видно, наскільки оцінки кожного студента відрізняються від кращих результатів групи.
SQL-код:
SELECT
s.name AS student_name,
g.grade AS student_grade,
(
SELECT MAX(grade) -- цей запит повертає одне єдине значення
FROM grades
INNER JOIN students ON grades.student_id = students.student_id
WHERE students.group_id = s.group_id
) AS max_group_grade
FROM
students s
INNER JOIN
grades g ON s.student_id = g.student_id;
Що тут відбувається:
- Для кожного студента ми отримуємо його ім’я та оцінку (
s.name,g.grade). SELECT MAX(grade)— це підзапит, який повертає максимальну оцінку всередині групи студента.- Підзапит виконується для кожного рядка основного запиту й використовує умову
WHERE students.group_id = s.group_id, щоб обмежити вибірку однією групою.
Приклад 2: Середня оцінка по групі
Хочеш бути ще кориснішим для аналітиків? Додамо у вивід не тільки максимальну оцінку, а й середню оцінку по групі.
SQL-код:
SELECT
s.name AS student_name,
g.grade AS student_grade,
(
SELECT AVG(grade)
FROM grades
INNER JOIN students ON grades.student_id = students.student_id
WHERE students.group_id = s.group_id
) AS avg_group_grade
FROM
students s
INNER JOIN
grades g ON s.student_id = g.student_id;
Тепер:
- Замість
MAX()ми використовуємоAVG()для обчислення середньої оцінки в групі. - Отримуємо "живий" аналіз даних.
Обмеження та рекомендації
Підзапити в SELECT потужні, але їх використання вимагає обережності:
- Продуктивність. Кожен підзапит виконується для кожного рядка основного запиту. Це може сповільнити виконання SQL-запиту, якщо таблиці великі. Наприклад, якщо в таблиці 1000 студентів, то підзапит виконається 1000 разів!
- Індекси. Для прискорення виконання таких запитів важливо правильно індексувати стовпці, які беруть участь в умовах
WHEREпідзапиту. - Читабельність. Намагайся уникати зайвої вкладеності. Якщо підзапити стають занадто складними, подумай про перенесення їх у
FROMабо створення тимчасових таблиць.
Приклади використання
Давай розглянемо ще кілька цікавих кейсів.
Приклад 3: Кількість курсів у кожного студента
Виводимо таблицю, де для кожного студента показується кількість курсів, на які він записаний. Таблиця enrollments пов’язана зі студентами по student_id:
| student_id | course_id |
|---|---|
| 1 | 201 |
| 1 | 202 |
| 2 | 201 |
| 3 | 203 |
SQL-код:
SELECT
s.name AS student_name,
(
SELECT COUNT(*)
FROM enrollments
WHERE enrollments.student_id = s.student_id
) AS course_count
FROM
students s;
Тут підзапит рахує кількість записів у таблиці enrollments для кожного студента.
Приклад 4: Флаг "відмінник" для кожного студента
Покажемо, чи є студент відмінником. Нехай критерій для відмінника — це наявність усіх своїх оцінок на рівні 5.
SQL-код:
SELECT
s.name AS student_name,
(
SELECT CASE
WHEN MIN(g.grade) = 5 THEN 'Відмінник'
ELSE 'Не відмінник'
END
FROM grades g
WHERE g.student_id = s.student_id
) AS status
FROM
students s;
Тут використовується вкладений CASE, щоб присвоїти статус "Відмінник" тільки тим студентам, у яких усі оцінки дорівнюють 5.
Оптимізація підзапитів у SELECT
Ми вже згадували, що продуктивність може стати проблемою. Ось кілька порад для її покращення:
- Використовуй індекси. Якщо підзапити фільтрують дані, переконайся, що на використовуваних стовпцях є індекси.
- Кешуй результати. Іноді доцільно винести підзапити у представлення (
VIEW) або тимчасові таблиці. - Менше вкладеності. Не зловживай багаторазовою вкладеністю, якщо можна використати простіший підхід.
Підзапити у SELECT відкривають купу можливостей для обчислень і аналізу даних. Хоч вони можуть бути ресурсоємними, їх правильно оптимізоване використання робить SQL набагато виразнішим і гнучкішим. Тож не соромся експериментувати й знаходити свої способи покращувати запити!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ