В прошлом уроке мы научились соединять таблицы через JOIN. Но часто тестировщику нужно не просто увидеть связанные строки, а посчитать что-то по ним: сколько студентов на курсе, какая средняя цена, сколько всего записей. Для этого в SQL есть агрегатные функции и группировка GROUP BY.
Чему научишься за этот урок:
— называть основные агрегатные функции: COUNT, SUM, AVG, MAX, MIN;
— объяснять, что делает GROUP BY и чем он отличается от запроса без группировки;
— писать запрос, который считает агрегат ОТДЕЛЬНО для каждой группы;
— проверять SQL-запросом цифру, которую продукт показывает в интерфейсе.
Агрегатные функции
Агрегатные функции — это функции, которые считают одно итоговое значение по набору строк, а не возвращают сами строки. Основные:
COUNT() -> количество строк SUM() -> сумма значений столбца AVG() -> среднее значение столбца MAX() -> максимальное значение MIN() -> минимальное значение
Например, SELECT COUNT(*) FROM enrollments; посчитает ОДНО общее число — сколько всего строк (записей на курсы) в таблице enrollments, без разбивки по курсам.
GROUP BY — считаем отдельно по каждой группе
GROUP BY группирует строки по значению столбца, и агрегатная функция считается ОТДЕЛЬНО для каждой группы, а не для всей таблицы сразу. Сравним два запроса к одной и той же таблице enrollments(id, user_id, course_id):
Без GROUP BY: SELECT COUNT(*) FROM enrollments; -> одно общее число записей по всей таблице С GROUP BY: SELECT course_id, COUNT(*) FROM enrollments GROUP BY course_id; -> по одной строке РЕЗУЛЬТАТА на каждый course_id, и в каждой строке - число записей именно на этот курс
То есть первый запрос скажет «всего 42 записи на курсы», а второй — «на курс 5 записано 30 человек, на курс 7 — 12 человек» (по строке на каждый курс отдельно).
Практическая польза: проверка цифры продукта
На странице курса в интерфейсе продукта может быть написано «На курсе 42 студента». Тестировщик может ПРОВЕРИТЬ это число SQL-запросом: SELECT COUNT(*) FROM enrollments WHERE course_id = 5; — и сравнить результат с тем, что показывает интерфейс. Если числа не совпадают — это баг: либо ошибка в расчёте на бэкенде, либо ошибка в отображении на фронтенде.
Итог:
— агрегатные функции COUNT, SUM, AVG, MAX, MIN считают одно итоговое значение по набору строк;
— GROUP BY группирует строки по столбцу, и агрегат считается ОТДЕЛЬНО для каждой группы;
— без GROUP BY агрегат даёт одно общее число по всей таблице;
— тестировщик может SQL-запросом проверить любую цифру, которую продукт показывает в интерфейсе.
Контрольный вопрос. Что делает агрегатная функция COUNT()?
Подсказка: Название функции прямо намекает на то, что она делает — посчитай.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. Что делает оператор GROUP BY?
Подсказка: Ключевое слово — «группирует»: подумай, что происходит с агрегатной функцией внутри каждой группы.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. Что вернёт запрос SELECT COUNT(*) FROM enrollments; (без GROUP BY)?
Подсказка: В уроке прямо сравниваются запрос без GROUP BY и запрос с ним — вспомни разницу.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. Какая функция посчитает среднюю цену по столбцу price?
Подсказка: Нужна именно функция среднего значения — посмотри список агрегатных функций урока.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. Запрос SELECT course_id, COUNT(*) FROM enrollments GROUP BY course_id; выполнили на таблице enrollments. Какие утверждения про результат верны (выбери все подходящие)?
Выберите все верные варианты.
Подсказка: Сверь каждое утверждение с примером из урока про GROUP BY course_id — одно из четырёх описывает поведение БЕЗ группировки.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. Как называется агрегатная функция, которая находит МАКСИМАЛЬНОЕ значение столбца? Ответь одним словом по-английски, как в уроке.
Подсказка: Посмотри список агрегатных функций урока — какая из них про максимум.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Задание. В интерфейсе продукта на странице курса с id=5 написано «На курсе 30 студентов». Какой SQL-запрос к таблице enrollments(id, user_id, course_id) проверит это число? Ответь одной командой SQL.
Подсказка: Нужен COUNT(*) с условием WHERE по нужному course_id.
✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Задание. Выполнили запрос SELECT course_id, COUNT(*) FROM enrollments GROUP BY course_id; и получили две строки результата: course_id=5 с числом 30, course_id=7 с числом 12. Сколько ВСЕГО строк в таблице enrollments (если это единственные два курса)? Ответь числом.
Подсказка: Сложи числа из каждой группы — это и есть общее количество записей по всей таблице.
✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Задание. Объясни в 2-3 предложениях: почему запрос SELECT COUNT(*) FROM enrollments; и запрос SELECT course_id, COUNT(*) FROM enrollments GROUP BY course_id; дают разные по смыслу результаты, хотя оба используют COUNT(*) на одной и той же таблице?
Критерий приёмки: объяснено, что первый запрос считает COUNT(*) по ВСЕЙ таблице целиком и даёт одно общее число; второй запрос сначала группирует строки по course_id, а затем считает COUNT(*) ОТДЕЛЬНО внутри каждой группы, поэтому даёт по строке результата на каждый курс с числом записей именно по этому курсу.
Подсказка: Вспомни, что делает GROUP BY с набором строк ДО того, как к ним применяется агрегатная функция.
✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.
Онлайн-проверка ответа появится позже
Задание. Тестировщик видит в интерфейсе продукта на странице каталога курсов надпись «Средняя цена курса: 4500 рублей». Опиши план проверки: (а) какой SQL-запрос к таблице courses(id, title, price) выполнить, чтобы проверить эту цифру; (б) что делать, если результат запроса не совпадёт с 4500 — на что в первую очередь обратить внимание при расследовании расхождения (например, может ли расхождение объясняться округлением или курсами без указанной цены).
Критерий приёмки: (а) назван запрос вида SELECT AVG(price) FROM courses; (б) описан план расследования: проверить, не отличается ли округление на фронтенде от округления в SQL-результате, и не исключены ли из среднего на бэкенде курсы с price = NULL или price = 0 (что сдвинуло бы среднее), — то есть указано хотя бы одно правдоподобное объяснение расхождения, а не просто «это баг».
Подсказка: AVG уже был в списке агрегатных функций урока; расхождение не всегда значит баг — подумай про округление и про курсы без цены.
✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.
Онлайн-проверка ответа появится позже
Что дальше
Теперь вы умеете считать агрегаты по группам и проверять ими цифры продукта. В следующем уроке разберём подзапросы — SQL-запросы внутри других запросов, которые иногда удобнее JOIN для разовой ручной проверки.
