JavaRush /Курси /SQL SELF /Використання підзапитів у FROM

Використання підзапитів у FROM

SQL SELF
Рівень 14 , Лекція 1
Відкрита

Давай ще глибше зануримось у кролячу нору: розглянемо, як використовувати підзапити в конструкції FROM. Це один із найчастіших підходів у SQL, бо дозволяє створювати потужні тимчасові таблиці прямо "на місці" і переюзати їх, ніби вони реально існують у базі.

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

  • Тимчасово об'єднувати дані або агрегувати їх перед основним запитом.
  • Створювати структуровані набори даних "на льоту".
  • Зменшити кількість операцій, вимагаючи від бази мінімального збереження проміжних даних.

Підзапити у FROM працюють як міні-таблиці, які ти можеш юзати в основному запиті. Це схоже на збірку модульного конструктора: швидко, гнучко і без зайвих заморочок :)

Базові речі про підзапити у FROM

У підзапитах у FROM ми створюємо тимчасову таблицю (або підтаблицю), яка стає частиною загального запиту. Для цього треба зробити три ключові кроки:

  1. Написати підзапит у конструкцію FROM у круглих дужках.
  2. Дати аліас (псевдонім) підзапиту.
  3. Використовувати цей псевдонім, як повноцінну таблицю.

Синтаксис

SELECT колонки
FROM (
    SELECT колонки
    FROM таблиця
    WHERE умова
) AS псевдонім
WHERE зовнішня_умова;

Звучить трохи страшно? Давай до прикладів.

Приклад: Студенти і середній бал

Припустимо, у нас є дві таблиці:

students (дані про студентів — їх ім'я та ID):

student_id student_name
1 Alex
2 Anna
3 Dan

grades (дані про оцінки студентів):

grade_id student_id grade
1 1 80
2 1 85
3 2 90
4 3 70
5 3 75

Тепер задача: отримати список студентів і їхній середній бал.

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

SELECT s.student_name, g.avg_grade
FROM (
    SELECT student_id, AVG(grade) AS avg_grade
    FROM grades
    GROUP BY student_id
) AS g
JOIN students AS s ON s.student_id = g.student_id;

Результат:

student_name avg_grade
Alex 82.5
Anna 90.0
Dan 72.5

Тимчасові таблиці "на льоту"

Підзапити у FROM особливо корисні, коли треба зробити більше одного рівня обробки даних. Наприклад, якщо хочеш не просто отримати середній бал, а й порахувати максимальний бал для кожного студента — все в одному запиті.

SELECT g.student_id, g.avg_grade, g.max_grade
FROM (
    SELECT student_id, 
           AVG(grade) AS avg_grade, 
           MAX(grade) AS max_grade
    FROM grades
    GROUP BY student_id
) AS g;

Результат:

student_id avg_grade max_grade
1 82.5 85
2 90 90
3 72.5 75

Зверни увагу, що це працює як повноцінна тимчасова таблиця зі своїми аналогами стовпців: avg_grade і max_grade.

Коли підзапити у FROM найкраще використовувати?

Для агрегованих даних. Якщо хочеш спочатку зробити підрахунки (наприклад, порахувати середнє, суми чи максимуми), а потім об'єднати результати з іншими таблицями.

Для фільтрації даних. Коли треба відфільтрувати дані до об'єднання з основною таблицею.

Для спрощення складних запитів. Розділення складних задач на етапи допомагає уникнути плутанини.

Приклад: Звіт про студентів з двома рівнями обробки

Уявімо, що хочемо знайти студентів, у яких середній бал більше 80. Почнемо з підзапиту, який рахує середні бали, і потім використаємо його у фільтрі.

SELECT s.student_name, g.avg_grade
FROM students AS s
JOIN (
    SELECT student_id, AVG(grade) AS avg_grade
    FROM grades
    GROUP BY student_id
) AS g ON s.student_id = g.student_id
WHERE g.avg_grade > 80;

Результат:

student_name avg_grade
Alex 82.5
Anna 90.0

Особливості використання та поради

Обов'язковий псевдонім. Завжди давай аліас підзапиту (наприклад, AS g), інакше PostgreSQL не зрозуміє, як звертатись до цієї "тимчасової таблиці".

Оптимізація. Підзапити у FROM можуть бути повільніші за об'єднання таблиць (JOIN), особливо якщо ти фільтруєш дані всередині підзапиту.

Індексація. Переконайся, що поля для об'єднання, індекси і фільтри оптимізовані — це дуже впливає на швидкість.

Приклад складного запиту: курси і кількість студентів

Тепер давай зробимо реальну задачу складніше. Уяви, що є така таблиця:

courses (список курсів):

course_id course_name
1 SQL Basics
2 Python Basics

І enrollments (записи студентів на курси):

student_id course_id
1 1
1 2
2 1

Тепер хочемо дізнатись, скільки студентів записано на кожен курс.

SELECT c.course_name, e.students_count
FROM courses AS c
JOIN (
    SELECT course_id, COUNT(student_id) AS students_count
    FROM enrollments
    GROUP BY course_id
) AS e ON c.course_id = e.course_id;

Результат:

course_name students_count
SQL Basics 2
Python Basics 1

Сподіваюсь, лекція тобі зайшла... але наступна буде ще цікавіша :)

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ